AQS(AbstractQueuedSynchronizer)
是一個抽象同步隊列,JUC(java.util.concurrent)
中不少同步鎖都是基於AQS
實現的。java
AQS
的基本原理就是當一個線程請求共享資源的時候會判斷是否可以成功操做這個共享資源,若是能夠就會把這個共享資源設置爲鎖定狀態,若是當前共享資源已經被鎖定了,那就把這個請求的線程阻塞住,也就是放到隊列中等待。編程
AQS
中有一個被volatile
聲明的變量用來表示同步狀態提供了getState()
、setState()
和compareAndSetState()
方法來修改state
狀態的值併發
// 返回同步狀態的當前值 protected final int getState() { return state; } // 設置同步狀態的值 protected final void setState(int newState) { state = newState; } // CAS操做修改state的值 protected final boolean compareAndSetState(int expect, int update) { return unsafe.compareAndSwapInt(this, stateOffset, expect, update); }
上面說了AQS
是JUC
中不少同步鎖的底層實現,鎖也分不少種,有像ReentrantLock
這樣的獨佔鎖,也有ReentrantReadWriteLock
這樣的共享鎖,因此AQS
中也必然是包含這兩種操做方式的邏輯ide
獨佔式ui
acquire()
方法,這裏面會調用tryAcquire()
方法去設置state
變量,若是失敗的話就把當前線程放入一個Node
中存入隊列public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
realase()
方法,會調用tryRelease()
方法修改state
變量,調用成果後會去喚醒隊列中Node
裏的線程,unparkSuccessor()
方法就是判斷當前state
變量是否符合喚醒的標準,若是合適就喚醒,不然繼續放回隊列public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; }
tryAcquire()
和tryRelease()
方法在AQS
中都是空的,前面說了JUC
中不少同步鎖都是基於AQS
實現,因此加鎖和釋放鎖的邏輯都還不肯定,所以是要在這些同步鎖中實現這兩個方法protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException(); } protected boolean tryRelease(int arg) { throw new UnsupportedOperationException(); }
共享式this
獲取資源會調用acquireShared()
方法,會調用tryAcquireShared()
操做state
變量,若是成功就獲取資源,失敗則放入隊列線程
public final void acquireShared(int arg) { if (tryAcquireShared(arg) < 0) doAcquireShared(arg); }
釋放資源是調用releaseShared()
方法,會調用tryReleaseShared()
設置state
變量,若是成功就喚醒隊列中的一個Node
裏的線程,不知足喚醒條件則還放回隊列中code
public final boolean releaseShared(int arg) { if (tryReleaseShared(arg)) { doReleaseShared(); return true; } return false; }
和獨佔式同樣,tryAcquireShared()
和tryReleaseShared()
也是須要子類來提供對象
protected int tryAcquireShared(int arg) { throw new UnsupportedOperationException(); } protected boolean tryReleaseShared(int arg) { throw new UnsupportedOperationException(); }
Condition
中的signal()
和await()
方法相似與notify()
和wait()
方法,須要和AQS
鎖配合使用。隊列
public static void main(String[] args) throws InterruptedException { ReentrantLock lock = new ReentrantLock(); Condition condition = lock.newCondition(); Thread thread1 = new Thread(new Runnable() { @Override public void run() { lock.lock(); System.out.println(" t1 加鎖"); System.out.println("t1 start await"); try { condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t1 end await"); lock.unlock(); } }); thread1.start(); Thread thread2 = new Thread(new Runnable() { @Override public void run() { lock.lock(); System.out.println(" t2 加鎖"); System.out.println("t2 start signal"); condition.signal(); System.out.println("t2 end signal"); lock.unlock(); } }); thread2.start(); }
AQS
中的原理上面lock.newCondition()
實際上是new
一個AQS
中ConditionObject
內部類的對象出來,這個對象裏面有一個隊列,當調用await()
方法的時候會存入一個Node
節點到這個隊列中,而且調用park()
方法阻塞當前線程,釋放當前線程的鎖。而調用singal()
方法則會移除內部類中的隊列頭部的Node
,而後放入AQS
中的隊列中等待執行機會
AQS
並無實現newCondition()
方法,也是須要子類本身去實現本文內容大部分都是閱讀了<<Java併發編程之美>>
這本書的內容,主要講了整個AQS
的大體原理,和幾個最重要的方法,其實整個AQS
的源碼是很複雜的,可是瞭解大體原理已經對咱們熟悉運用那些JUC
中的同步鎖有很大的幫助。