Java中的AbstractQueuedSynchronizer
(AQS)是Java并發框架的核心組件之一,它位于java.util.concurrent.locks
包下。AQS為Java的鎖和其他同步工具提供了基礎架構,它使用模板設計模式和一種稱為“CLH鎖”的算法來實現高效的線程同步。
AQS的主要組成部分
AQS的主要功能圍繞著一個volatile整型成員變量state
和一個FIFO線程等待隊列來組織。state
變量用于表示同步狀態,比如鎖是否被持有,有多少線程正在持有鎖等。這個狀態變量是通過原子更新的方式來保證線程安全性。
CLH鎖算法
AQS使用CLH鎖算法(Craig, Landin, and Hagersten)來管理線程間的同步。CLH鎖算法的特點是使用了一個尾指針(tail pointer)來標識隊列的末端,新來的線程會將其自身添加到隊列的尾部,并且將自己設置為隊列的新的尾節點。當線程從等待隊列中被喚醒時,它會檢查前一個節點的狀態,以確定是否可以嘗試獲取鎖。
AQS的關鍵方法
AQS提供了一些關鍵的方法,它們被子類重寫以適應特定的同步需求:
isHeldExclusively()
:判斷當前同步狀態是否是獨占模式。tryAcquire(int)
?和?tryRelease(int)
:嘗試獲取和釋放同步狀態,這兩個方法由子類實現,用于具體的操作。tryAcquireShared(int)
?和?tryReleaseShared(int)
:嘗試獲取和釋放共享模式下的同步狀態。acquire(int)
?和?acquireShared(int)
:如果無法立即獲取同步狀態,這些方法會將當前線程放入等待隊列并阻塞當前線程。release(int)
?和?releaseShared(int)
:釋放同步狀態,如果這是最后一個持有同步狀態的線程,它會喚醒等待隊列中的下一個線程。
AQS的子類
AQS的子類包括但不限于:
ReentrantLock
:可重入的互斥鎖。Semaphore
:信號量,用于控制對有限數量資源的訪問。CountDownLatch
:倒計時門閂,用于等待一組操作完成。CyclicBarrier
:循環柵欄,用于等待固定數量的線程到達某個點。ReadWriteLock
:讀寫鎖,允許多個讀線程同時訪問資源,但不允許讀線程和寫線程或者兩個寫線程同時訪問。
AQS的工作流程
當線程試圖獲取同步狀態時,AQS會調用tryAcquire
或tryAcquireShared
方法。如果同步狀態無法立即獲取,線程會被插入到等待隊列中,并且線程會被阻塞。當同步狀態被釋放時,AQS會喚醒等待隊列中的一個或多個線程,使其有機會再次嘗試獲取同步狀態。
總結
AQS是Java并發包中的一個高度抽象和靈活的工具,它通過模板方法和鉤子函數(hook methods)的設計模式,為開發者提供了構建各種同步組件的基礎。通過重寫AQS提供的方法,開發者可以輕松地實現自定義的同步邏輯,而不需要關心線程調度和同步狀態的底層細節。AQS的使用,大大簡化了Java中并發控制組件的開發和維護。