深度解析:AQS原理

  AQS的全稱是AbstractQueuedSynchrizeder(抽象隊列同步器)。它是爲實現依賴於先進先出等待隊列的阻塞鎖和各種同步器(Semaphore,CountdownLatch,CyclicBarrier,Exchanger等等)而提供的一種基礎框架。

  它內部有一個int類型的state變量,被volatile關鍵字修飾,保證線程之間的可見。還會維護一個Node內部類(用於生成同步對列和等待隊列),並繼承過來一個加鎖線程。state變量的訪問方式有三種:getState(),setState(int),compareAndSetState(int,int)三個方法。AQS定義了兩種資源共享的方式,獨佔模式和共享方式。

  使用此類:

   爲了將此類用作同步器的基礎,需要適當的重新定義以下方法,這是通過使用getState(),setState(int),compareAndSetState(int,int)三個方法來檢查或修改同步狀態來實現的。

        tryAcquire(int)       試圖在獨佔模式下獲取對象狀態,由acquire自動調用,至少調用一次

        tryRelease(int)      試圖設置狀態來反映獨佔模式下的一個釋放,由release自動調用,至少調用一次

        tryAcquireShared(int)         試圖在共享模式下獲取對象狀態,由acquireShared自動調用,至少調用一次

         tryReleaseShared(int)      試圖設置狀態來反映共享模式下的一個釋放,由releaseShared自動調用,至少調用一次

  默認情況下,每個方法都拋出UnsupportedOperationException。這些方法的實現在內部必須是線程安全的,通常應該很短並且不被阻塞。

 

  ReentrantLock就是使用AQS而實現的一把鎖,它實現了可重入鎖,公平鎖和非公平鎖。它有一個內部類用作同步器是Sync,Sync是繼承了AQS的一個子類,並且公平鎖和非公平鎖是繼承了Sync的兩個子類。ReentrantLock的原理是:假設有一個線程A來嘗試獲取鎖,它會先CAS修改state的值,從0修改到1,如果修改成功,那就說明獲取鎖成功,設置加鎖線程爲當前線程。如果此時又有一個線程B來嘗試獲取鎖,那麼它也會CAS修改state的值,從0修改到1,因爲線程A已經修改了state的值,那麼線程B就會修改失敗,然後他會判斷一下加鎖線程是否爲自己本身線程,如果是自己本身線程的話它就會將state的值直接加1,這是爲了實現鎖的可重入。如果加鎖線程不是當前線程的話,那麼就會將它生成一個Node節點,加入到等待隊列的隊尾,直到什麼時候線程A釋放了鎖它會喚醒等待隊列隊頭的線程。這裏還要分爲公平鎖和非公平鎖,默認爲非公平鎖,公平鎖和非公平鎖無非就差了一步。如果是公平鎖,此時又有外來線程嘗試獲取鎖,它會首先判斷一下等待隊列是否有第一個節點,如果有第一個節點,就說明等待隊列不爲空,有等待獲取鎖的線程,那麼它就不會去同步隊列中搶佔cpu資源。如果是非公平鎖的話,它就不會判斷等待隊列是否有第一個節點,它會直接前往同步對列中去搶佔cpu資源。

  以下是ReentrantLock的原理圖解,簡單明瞭:

 

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