Lock

Lock相對於synchronized關鍵字的優點:框架

  • 能夠顯式的加鎖解鎖,更有操做性
  • 獲取到鎖的線程可以響應中斷,當獲取到鎖的線程倍中斷是,中斷異常將會被拋出,勇士鎖會被釋放
  • 超時獲取鎖,在指定的截止時間以前獲取鎖,若是截止時間到了仍舊沒法得到鎖,則返回

Lock的API:ui

隊列同步器AbstractQueuedSynchronizer,使用來構建鎖或者其餘同步組件的基礎框架,鎖是面向使用者的。它定義了使用者與鎖交互的接口,隱藏了實現細節;同步器面向的是鎖的實現者,它簡化了鎖的實現方式,屏蔽了同步狀態管理、線程的排隊、等待與喚醒等底層操做。線程

 

同步器使用了模板方法模式,從新同步器指定的方法時,須要使用同步器提供的以下3個方法來訪問或修改同步狀態:設計

getState():獲取當前同步狀態接口

setState(int newState):設置當前同步狀態隊列

compareAndSetState(int expect, int update):使用CAS設置當前狀態,該方法可以保證狀態設置的原子性get

 

同步器依賴內部的同步隊列(一個FIFO雙向隊列)來完成同步狀態管理同步

同步隊列準訊FIFO,首節點是獲取同步狀態成功的節點,首節點的線程在釋放同步狀態時,將會喚醒後續節點,然後續節點將會在獲取同步狀態成功時將本身設置爲首節點,以下:it

獨佔式同步狀態獲取流程,也就是acquire(int arg)方法調用流程,以下圖:io

獨佔獲取鎖的過程:

  1. 調用tryAcquire(int arg)這個方法的實現中公平鎖和非公平鎖有點區別,公平鎖會判斷隊列是否爲空,若是爲空或者當前線程是首節點的下一個節點(正好在輪詢CAS)這嘗試CAS更改一次鎖狀態,若是失敗進入下一步;
  2. 將當前線程封裝成一個獨佔Node使用CAS自旋加入隊列尾部,而且自旋搶奪鎖,不過因爲判斷條件會判斷當前節點是否爲首節點的子節點,因此非第二個節點並不會真的發起CAS;
  3. 當前節點判斷前一個節點爲狀態爲0,會在設置狀態爲SIGNAL(-1),下一次循環當前一個節點爲SIGNAL,當前線程陷入等待;

 

共享鎖和獨佔鎖的區別主要是鎖狀態的區別,獨佔鎖狀態只有0--空閒1--獨佔,共享鎖能夠>1,每次加鎖數字加1,解鎖-1,或者像Semaphore的實現,根據傳入的許可證總數permits,每次加鎖自減1,當值爲0時,加鎖失敗,加入同步隊列

 

獨佔超時同步狀態獲取流程,以下圖:

ReentrantReadWriteLock:

鎖狀態設計頗有意思使用一個int值,高16位表示讀鎖狀態,低16位表示寫鎖狀態。

 

寫鎖持有狀態,除了持有鎖的線程能夠重入加寫鎖,或者加讀鎖,其餘線程不能加鎖。

讀鎖持有狀態,其餘線程能夠加讀鎖不能加寫鎖。

 

LockSupport方法:

 

Condition方法:

相關文章
相關標籤/搜索