
前言
Java 的鎖實作,有 Synchronized 和 Lock,上一篇文章深入分析了 Synchronized 的實作原理:由Java 15廢棄偏向鎖,談談Java Synchronized 的鎖機制,
本篇文章深入分析 Lock 的實作,以及對比其與 Synchronized 的不同,
Synchronized 與 Lock 的對比
- 實作方式:Synchronized 由 JVM 實作;Lock 由 Java 底層代碼實作
- 鎖獲取:Synchronized 是 JVM 隱式獲取,不用 Java 代碼;Lock 由 Java 代碼實作,有多種獲取方式
- 鎖的釋放:Synchronized 是 JVM 隱式釋放,不用 Java 代碼;Lock 可通過
Lock.unlock(),在 finally 中釋放 - 鎖的型別:
Synchronized 是非公平、可重入的,Lock 是非公平性、公平性、可重入的 - 鎖的中斷:Synchronized 不支持中斷,Lock 支持中斷
實作原理
Lock 是一個介面類,其介面方法定義:

lock():獲取鎖lockInterruptibly():如果當前執行緒未被中斷,則獲取鎖,可以回應中斷tryLock():僅在呼叫時鎖為空閑狀態才獲取該鎖,可以回應中斷tryLock(long time, TimeUnit unit):如果鎖在給定的等待時間內空閑,并且當前執行緒未被中斷,則獲取鎖unlock():釋放鎖newCondition():回傳系結到此 Lock 實體的新 Condition 實體
基礎原理就不贅述了,Lock 介面的常用類:
- ReentrantLock(重入鎖)
- ReentrantReadWriteLock(可重入的讀寫鎖)
其都是依賴 AQS 實作的,AQS 類結構中包含一個基于鏈表實作的等待佇列(CLH 佇列),用于存盤所有阻塞的執行緒,AQS 中還有一個 state 變數,表示加鎖狀態,
ReentrantLock

ReentrantReadWriteLock
ReentrantLock 是獨占鎖,對于同一份資料,如果一個執行緒讀資料,另一個執行緒在寫資料,那么讀到的資料與最終的資料可能不一致,
在實際的業務場景中,讀操作遠遠大于寫操作,在多執行緒編程中,讀操作不會修改共享資源的資料,針對讀多寫少的場景,我們可以使用 ReentrantReadWriteLock 來優化,ReentrantReadWriteLock 內部維護了 2 個鎖:讀鎖 ReadLock,寫鎖 WriteLock,
規則簡單概括為:
- 如果寫鎖沒有被占用,就可以獲取讀鎖
- 如果讀鎖沒有被占用,才可以獲取寫鎖
下面的測驗代碼,因為讀鎖和寫鎖是同時 lock 的,所以會死鎖,
@Test
public void testReadWriteLock() {
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.readLock().lock();
lock.writeLock().lock();
System.out.println("Hello");
lock.readLock().unlock();
lock.writeLock().unlock();
}
StampedLock
上述 ReentrantReadWriteLock 會有一個問題:在讀很多,寫很少的情況下,執行緒會因一直無法獲取到鎖而處于等待狀態,
在 JDK 1.8 中,Java 提供了 StampedLock,有三種模式:
- 寫
- 悲觀讀
- 樂觀讀
一個寫執行緒獲取寫鎖,通過 WriteLock 獲取票據 stamp,WriteLock 是一個獨占鎖,unlockWrite 需要傳遞引數 stamp,
不一樣的地方在于讀程序,執行緒會先通過樂觀鎖 tryOptimisticRead 獲取票據 stamp,如果當前沒有執行緒持有寫鎖,則會回傳一非 0 的 stamp 資訊,執行緒獲取該 stamp 后,會拷貝一份共享資源到房發展,
之后方法還需要呼叫 validate,驗證之前呼叫 tryOptimisticRead 回傳的 stamp 在當前是否有其它執行緒持有了寫鎖,如果是,那么 validate 會回傳 0,升級為悲觀鎖;否則就可以使用該 stamp 版本的鎖對資料進行操作,
總結
相比于 Synchronized 同步鎖,Lock 實作的鎖更加靈活:
- 可以分為讀寫鎖,優化讀大于寫的場景
- 可以中斷
- 可以超時
- 可以區分公平性
公眾號
coding 筆記、點滴記錄,以后的文章也會同步到公眾號(Coding Insight)中,希望大家關注_
代碼和思維導圖在 GitHub 專案中,歡迎大家 star!

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/231767.html
標籤:其他
上一篇:圖的代碼實作 (鄰接矩陣)
