基礎概念:隱式鎖 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更高。