JUC之 底層核心AQS

AQS,AbstractQueuedSynchronizer,即隊列同步器。它是構建鎖或者其他同步組件的基礎框架(如ReentrantLock、ReentrantReadWriteLock、Semaphore等)

 

AQS使用一個int類型的成員變量state來表示同步狀態,當state>0時表示已經獲取了鎖,當state = 0時表示釋放了鎖。它提供了三個方法(getState()、setState(int newState)、compareAndSetState(int expect,int update))來對同步狀態state進行操作,當然AQS可以確保對state的操作是安全的。

 

AQS通過內置的FIFO同步隊列來完成資源獲取線程的排隊工作,如果當前線程獲取同步狀態失敗(鎖)時,AQS則會將當前線程以及等待狀態等信息構造成一個節點(Node)並將其加入同步隊列,同時會阻塞當前線程,當同步狀態釋放時,則會把節點中的線程喚醒,使其再次嘗試獲取同步狀態。

 

AQS主要提供瞭如下一些方法:

  • getState():返回同步狀態的當前值;
  • setState(int newState):設置當前同步狀態;
  • compareAndSetState(int expect, int update):使用CAS設置當前狀態,該方法能夠保證狀態設置的原子性;
  • tryAcquire(int arg):獨佔式獲取同步狀態,獲取同步狀態成功後,其他線程需要等待該線程釋放同步狀態才能獲取同步狀態;
  • tryRelease(int arg):獨佔式釋放同步狀態;
  • tryAcquireShared(int arg):共享式獲取同步狀態,返回值大於等於0則表示獲取成功,否則獲取失敗;
  • tryReleaseShared(int arg):共享式釋放同步狀態;
  • isHeldExclusively():當前同步器是否在獨佔式模式下被線程佔用,一般該方法表示是否被當前線程所獨佔;
  • acquire(int arg):獨佔式獲取同步狀態,如果當前線程獲取同步狀態成功,則由該方法返回,否則,將會進入同步隊列等待,該方法將會調用可重寫的tryAcquire(int arg)方法;
  • acquireInterruptibly(int arg):與acquire(int arg)相同,但是該方法響應中斷,當前線程爲獲取到同步狀態而進入到同步隊列中,如果當前線程被中斷,則該方法會拋出InterruptedException異常並返回;
  • tryAcquireNanos(int arg,long nanos):超時獲取同步狀態,如果當前線程在nanos時間內沒有獲取到同步狀態,那麼將會返回false,已經獲取則返回true;
  • acquireShared(int arg):共享式獲取同步狀態,如果當前線程未獲取到同步狀態,將會進入同步隊列等待,與獨佔式的主要區別是在同一時刻可以有多個線程獲取到同步狀態;
  • acquireSharedInterruptibly(int arg):共享式獲取同步狀態,響應中斷;
  • tryAcquireSharedNanos(int arg, long nanosTimeout):共享式獲取同步狀態,增加超時限制;
  • release(int arg):獨佔式釋放同步狀態,該方法會在釋放同步狀態之後,將同步隊列中第一個節點包含的線程喚醒;
  • releaseShared(int arg):共享式釋放同步狀態;

實現原理:

 

 

  • 底層是雙向鏈表,隊列的一種實現
  • sync queue:同步隊列,head節點主要負責後面的調度
  • Condition queue:單向鏈表,不是必須的的,也可以有多個
  • 具體實現的思路

1.首先 AQS內部維護了一個CLH隊列,來管理鎖

  1. 線程嘗試獲取鎖,如果獲取失敗,則將等待信息等包裝成一個Node結點,加入到同步隊列Sync queue裏

3.不斷重新嘗試獲取鎖(當前結點爲head的直接後繼纔會 嘗試),如果獲取失敗,則會阻塞自己,直到被喚醒

4.當持有鎖的線程釋放鎖的時候,會喚醒隊列中的後繼線程


基於AQS的原理 實現 了很多組件:

  • CountDownLatch
  • Semaphore
  • CyclicBarrier
  • ReentrantLock
  • Condition
  • FutureTask

接下來會對CountDownLatch、Semaphore 、ReetrantLock進行深入分析。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章