基礎概念:隱式鎖 Synchronized 與顯示鎖 Lock的用法和簡單對比

轉自:https://blog.csdn.net/u011519624/article/details/61628611
Synchronized

Synchronized是Java的關鍵字,當它用來修飾一個方法或一個代碼塊時,能夠保證在同一時刻最多隻有一個線程執行該代碼。因爲當調用Synchronized修飾的代碼時,並不需要顯示的加鎖和解鎖的過程,所以稱之爲隱式鎖。

Sychronized的用法:

1、同步方法體,在方法聲明中使用,如下:

public synchronized void method(){
        //方法體
}

2、同步代碼塊,修飾在代碼塊外層,指定加鎖對象,如下:

public void method2(){
    synchronized (this) {
    //一次只能有一個線程進入   
    }
}

上述synchronized(this)指定了當前對象本身作爲鎖,和它持有相同對象鎖的地方將產生互斥性。當一個線程訪問method2的同步代碼塊時,它就獲得了這個object的對象鎖。其他的線程對該object所有同步代碼部分的訪問都被暫時的阻塞。

sychronized的不同寫法對程序響應的快慢和對資源高併發的利用程度不一樣,性能和執行效率從差到優排序如下:

同步方法體 < 同步代碼塊 < 小對象鎖同步代碼塊

小對象鎖同步代碼塊指鎖的對象的所佔內存小,因爲鎖是對象,加鎖和解鎖都需要釋放資源,那肯定是鎖對象越小越好,實際應用如下:

private byte[] lock = new byte[1];
public void method3(){
    synchronized (lock) {
        //一次只能有一個線程進入   
    }
}

Lock

Lock是一個接口,提供了無條件的、可輪詢的、定時的、可中斷的鎖獲取操作,所有的加鎖和解鎖操作方法都是顯示的,因而稱爲顯示鎖。
下面針對Lock的幾個實現類ReentrantLock、ReentrantReadWriteLock.ReadLock和ReentrantReadWriteLock.WriteLock解析。

ReentrantLock(可重入鎖),是一個互斥的同步器,用ReentrantLock實現同步機制比sychronized實現更具伸縮性。使用如下:

private final ReentrantLock lock = new ReentrantLock();
    public void m(){
        lock.lock();//獲得鎖
        try{
            //方法體
        }finally{
            lock.unlock();//務必釋放鎖
        }
    }

注意:在使用ReentrantLock時,一定要有釋放鎖的操作。

ReadWriteLock(讀寫鎖)是一個接口,提供了readLock和writeLock兩種鎖的操作,也就是說一個資源能夠被多個讀線程訪問,或者被一個寫線程訪問,但是不能同時存在讀寫線程。也就是說讀寫鎖應用的場景是一個資源被大量讀取操作,而只有少量的寫操作。我們先看其源碼:

public interface ReadWriteLock {
    Lock readLock();
    Lock writeLock();
}

從源碼看出,ReadWriteLock藉助Lock來實現讀寫兩個鎖並存、互斥的機制。每次讀取共享數據就需要讀取鎖,需要修改共享數據就需要寫入鎖。

讀寫鎖的機制:
1、讀-讀不互斥,讀線程可以併發執行;
2、讀-寫互斥,有寫線程時,讀線程會堵塞;
3、寫-寫互斥,寫線程都是互斥的。

使用方法:

//創建ReentrantReadWriteLock對象
    private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

    //抽取讀寫鎖
    private Lock readLock = rwl.readLock();
    private Lock writeLock = rwl.writeLock();
    public int getXXX(){
        readLock.lock();
        try{
            //執行操作
        }finally{
            readLock.unlock();
        }
    }
    public void setXXX(){
        writeLock.lock();
        try{
            //執行操作
        }finally{
            writeLock.unlock();
        }
    }

ReentrantReadWriteLock和ReentrantLock的比較:
ReentrantReadWriteLock是對ReentrantLock的複雜擴展,能適合更加複雜的業務場景,ReentrantReadWriteLock可以實現一個方法中讀寫分離的鎖的機制。而ReentrantLock只是加鎖解鎖一種機制。

最後對比Synchronized、ReentrantLock和ReentrantReadWriteLock:

Synchronized是在JVM層面上實現的,無需顯示的加解鎖,而ReentrantLock和ReentrantReadWriteLock需顯示的加解鎖,一定要保證鎖資源被釋放;
Synchronized是針對一個對象的,而ReentrantLock和ReentrantReadWriteLock是代碼塊層面的鎖定;
ReentrantReadWriteLock引入了讀寫和併發機制,可以實現更復雜的鎖機制,併發性相對於ReentrantLock和Synchronized更高。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章