多線程在并發(fā)過程中發(fā)生競爭時馍佑,其實都滿足以下語義:
當(dāng)共有狀態(tài)(state)滿足某種條件時条舔,線程執(zhí)行;若不滿足怨咪,則排隊(queue)等待(park)屋剑,直到被喚醒(unpark);
或者換一種表述:
當(dāng)線程獲取鎖時诗眨,則繼續(xù)執(zhí)行唉匾;否則排隊(queue)等待(park),直到被喚醒(unpark)辽话;
AQS實際上就是對上述基本語義的包裝實現(xiàn)肄鸽。
在不同的上下文中,滿足狀態(tài)的條件可能是不一樣的油啤,因此要由子類去實現(xiàn)典徘;而排隊等待包括等待后的喚醒行為應(yīng)該都是相同的,所以這一部分已經(jīng)由AQS實現(xiàn)完畢益咬。
AQS中定義了state變量來表示共有狀態(tài)逮诲,子類需要從該變量獲取共有狀態(tài)當(dāng)前的值帜平。
private volatile int state;
protected final int getState() { return state; }
protected final void setState(int newState) { state = newState; }
需要子類去實現(xiàn)的方法重要的有如下幾個,比如第一個方法梅鹦,若滿足狀態(tài)(獲得了鎖)裆甩,則要返回true,否則返回false齐唆。
//獨占鎖
protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException(); }
protected boolean tryRelease(int arg) { throw new UnsupportedOperationException(); }
//共享鎖
protected int tryAcquireShared(int arg) { throw new UnsupportedOperationException(); }
protected boolean tryReleaseShared(int arg) { throw new UnsupportedOperationException(); }
下表為各個類對state值的判斷
Class | state | 鎖類型 | 說明 |
---|---|---|---|
ReentrantLock | 0 或 非0 | 獨占鎖 | state可以理解為鎖的唯一一把鑰匙嗤栓,若為0,說明鑰匙沒人用箍邮,當(dāng)前線程獲取鑰匙開了鎖茉帅,其他線程都等待;否則若exclusiveThread==currentThread锭弊,則重入堪澎;否則阻塞 |
CountDownLatch | 是否大于0 | 共享鎖 | state可以理解為倒計時,若為0味滞,說明倒計時結(jié)束樱蛤,waiting()的線程可以執(zhí)行(可能有多個線程同時競爭執(zhí)行) |
Semaphore | 是否大于0 | 共享鎖 | 此時state可以理解為通行證,若大于0剑鞍,說明還有證書昨凡,當(dāng)前線程可以執(zhí)行;否則阻塞 |
ReentrantReadWriteLock.WriteLock | 0 或 非0 | 獨占鎖 | 獲取writeLock后蚁署,readLock無法再獲取 |
ReentrantReadWriteLock.ReadLock | 是否大于0 | 共享鎖 | 獲取reakLock后土匀,writeLock無法再獲取 |