從ReentrantLock看AQS (AbstractQueuedSynchronizer) 執行流程 抽象的佇列式同步器
ReentrantLock 是JDK提供的可重入鎖實現類,可用其替換synchronized來實現鎖重入效果;其底層實現主要是依靠AbstractQueuedSynchronizer,本文將通過ReentrantLock來觀察AbstractQueuedSynchronizer的執行流程。
這個類在java.util.concurrent.locks包
這個機制AQS是用CLH佇列鎖實現的,即將暫時獲取不到鎖的執行緒加入到佇列中。
CLH(Craig,Landin,and Hagersten)佇列是一個虛擬的雙向佇列,虛擬的雙向佇列即不存在佇列例項,僅存在節點之間的關聯關係。
AQS就是基於CLH佇列,用volatile修飾共享變數state,執行緒通過CAS去改變狀態符,成功則獲取鎖成功,失敗則進入等待佇列,等待被喚醒。
實現了AQS的鎖有:自旋鎖、互斥鎖、讀鎖寫鎖、條件產量、訊號量、柵欄都是AQS的衍生物
AQS 定義了兩種資源共享方式:
1.Exclusive:獨佔,只有一個執行緒能執行,如ReentrantLock
2.Share:共享,多個執行緒可以同時執行,如Semaphore、CountDownLatch、ReadWriteLock,CyclicBarrier
大體意思就是“提供一個框架,用於實現依賴於先進先出(FIFO)等待佇列的阻塞鎖和相關同步器(訊號量、事件等)”,AQS不是一個功能完整的類,而是一個提供了一套依賴於FIFO等待佇列的流程框架,該框架可用於實現鎖等同步器的。AQS中沒有使用任何鎖相關的API,其實現主要依靠CAS (Compare And Swap),是一個優秀的lock-free 程式設計實踐。
ReentrantLock 是使用AQS實現的,其主要是實現了AQS的tryAcquire
和tryRelease
方法,且只需要在lock
和unlock
方法中呼叫一下acquire
和release
方法即可,可以看出AQS非常強大!