JDK針對Lock的主要實現是ReentrantLock,ReadWriteLock實現是ReentrantReadWriteLock。本文主要介紹ReentrantLock。ide
兩把鎖共享一個等待隊列,兩把鎖的狀態都由一個原子變量表示,特有的獲取鎖和釋放鎖邏輯。性能
注: 這裏的響應中斷意思是若被其餘線程中斷(調用interrupt方法)會拋出InterruptedException異常。this
AQS-AbstractQueuedSynchronizer(抽象隊列同步器)。線程
ReadWriteLock在內部注入了AbstractQueuedSynchronizer,上鎖和釋放鎖核心方法都在AQS類當中,AQS維護了兩個核心變量,一個是state(當前可重入計數,初始值爲0),一個是exclusiveOwnerThread(當前持有鎖的線程Thread對象)。另外還維護了一個鎖等待隊列。code
ReentrantLock構造方法傳入的boolean值ture爲公平鎖,false爲不公平鎖。以不公平鎖爲例先講一下上鎖和釋放鎖的原理:對象
就是將AQS內的state變量的值遞減1,若是state值爲0,則完全釋放鎖,會將「加鎖線程」變量也設置爲null,同時喚醒等待隊列中的第一個線程。隊列
爲何說上面的是不公平鎖,釋放鎖時不是喚醒隊列中第一個線程嗎?爲何還會出現不公平的狀況了,緣由在於若是恰好釋放鎖,此時有一個線程進來嘗試獲取鎖,可能會存在插隊的狀況。同步
構造方法bollean傳入true則表明的是公平鎖,在獲取鎖方法中多了一個檢查,意義是隻有不存在其餘等待時間更長的線程,它纔會嘗試獲取鎖。對比不公平鎖,其總體性能比較低,低的緣由不是這個檢查慢,而是會讓活躍線程得不到鎖,進入等待狀態,引發上下文切換,下降了總體的效率,it
建議: synchronized之前的效率不如顯式鎖,但如今的版本二者效率上幾乎沒有區別,因此建議能用synchronized就用synchronized,須要實現synchronized辦不到的需求如以上區別時,再考慮ReentrantLock。io
與wait和notify對應,用於線程協做,經過Lock的Condition newCondition()方法建立對應顯示鎖的顯示條件;
主要方法是await()和signal(),await()對應於Object的wait(),signal()對應於notify,signalAll()對應於notifyAll()
public class WaitThread extends Thread { private volatile boolean fire = false; private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); @Override public void run() { try { lock.lock(); try { while (!fire) { condition.await(); } } finally { lock.unlock(); } System.out.println("fired"); } catch (InterruptedException e) { Thread.interrupted(); } } public void fire() { lock.lock(); try { this.fire = true; condition.signal(); } finally { lock.unlock(); } } public static void main(String[] args) throws InterruptedException { WaitThread waitThread = new WaitThread(); waitThread.start(); Thread.sleep(1000); System.out.println("fire"); waitThread.fire(); } }
當主線程調用fire方法時,子線程才被喚醒繼續執行。