1. 前言
Java鎖的種類 java中的鎖種類是真的多。而locks包下也有一些。包結構如下:
- AbstractOwnableSynchronizer 一個線程擁有的同步器,這個類提供了創建鎖和相關同步器的基礎
- AbstractQueuedLongSynchronizer 所有的同步狀態都是用long變量來維護的,而不是int,在需要64位的屬性來表示狀態的時候會很有用
- AbstractQueuedSynchronizer 爲實現依賴於先進先出隊列的阻塞鎖和相關同步器(信號量、事件等等)提供的一個框架,它依靠int值來表示狀態
- Condition 將 Object 監視器方法(wait、notify 和 notifyAll)分解成截然不同的對象,以便通過將這些對象與任意 Lock 實現組合使用,爲每個對象提供多個等待 set (wait-set)。其中,Lock 替代了 synchronized 方法和語句的使用。這個是被綁定在Lock上一起使用的。
- Lock 實現了比synchronized更多的功能,需要注意的是,爲了確保可以釋放鎖,需要在finally語句塊中unlock。
- LockSupport LockSupport是用來創建鎖和其他同步類的基本線程阻塞原語。LockSupport中的park() 和 unpark() 的作用分別是阻塞線程和解除阻塞線程,而且park()和unpark()不會遇到“Thread.suspend 和 Thread.resume所可能引發的死鎖”問題。
- ReadWriteLock 讀寫鎖,讀和寫是互斥的,多個讀鎖不互斥,也就是說,在讀的時候,不能寫,在寫的時候,不能讀,但是在讀的時候可以有多個線程同時讀。
- ReentrantLock 可重入鎖
- ReentrantReadWriteLock 可重入讀寫鎖
- StampedLock Java 1.8提供了一種讀寫鎖,
2. Condition
Condition是和Lock綁定使用的。Lock#newCondition方法返回一個Condition。
使用方法如下:
- 創建Lock
- Lock#newCondition 返回新的Condition (可以多次調用)
- Condition#await 會導致線程掛起直到signalled,或者中斷。
- Condition#signal 喚醒線程
ArrayBlockingQueue中有大量這樣的用法。如圖:
3. LockSupport
- park方法能將阻塞線程或者
- unpark 方法喚醒線程
4. ReentrantReadWriteLock
ReentrantReadWriteLock是locks包中提供的讀寫鎖的一種實現,用法也很簡單。一般用jdk提供的ReentrantReadWriteLock。
用法如下
- 初始化
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
Lock readLock = readWriteLock.readLock();
Lock writeLock = readWriteLock.writeLock();
- 在需要讀的時候
readLock.lock()
,用完之後readLock.unlock()
- 在需要寫的時候
writeLock.lock()
,用完之後writeLock.unlock()
ReentrantReadWriteLock支持鎖降級
什麼是鎖降級呢。從讀寫角度來看,寫的級別是高於讀的。咱們看例子
public static void main(String[] args){
ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
final Lock readLock = readWriteLock.readLock();
final Lock writeLock = readWriteLock.writeLock();
// 讀
readLock.lock();
System.err.println("我是讀鎖");
// 寫
writeLock.lock();
System.err.println("我是寫鎖");
}
很明顯,由於不支持鎖升級,因此,會阻塞。輸出結果如下
我們上面讀寫翻個順序。
// 寫
writeLock.lock();
System.err.println("我是寫鎖");
// 讀
readLock.lock();
System.err.println("我是讀鎖");
輸出結果如下:
鎖降級,將寫入鎖降級爲讀鎖(很好理解,就像寫權限要高於讀權限一樣)
5. ReentrantLock
也叫做遞歸鎖,指的是同一線程 外層函數獲得鎖之後 ,內層遞歸函數仍然有獲取該鎖的代碼,但不受影響
這種鎖在ArrayBlockingQueue中有用到。
關於用法這裏就不說了。
ReentrantLock可是實現公平鎖
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
從構造函數中來看,是支持公平鎖的。
公平鎖,等待時間長的優先獲得鎖。
6. StampedLock
這裏想的半天,還是覺得參考資料裏面寫的很完美,所以,我就不獻醜了。大家去看看吧。
參考資料