摘要:前言本來準備做源碼閱讀的幾千行看著太累了看了幾篇大神的文章后才基本搞懂附在這里閱讀本文前請先看懂的介紹和原理分析并發包源碼學習之框架四源碼分析接口實現接口一般看一個類實現的接口可以看出它的目的其實也是熟悉的目的主要是替代的方法的它是基于實現
前言
本來準備做AbstractQueuedSynchronizer源碼閱讀的,幾千行看著太累了,看了幾篇大神的文章后才基本搞懂,附在這里,閱讀本文前請先看懂AQS
AbstractQueuedSynchronizer的介紹和原理分析
Java并發包源碼學習之AQS框架(四)AbstractQueuedSynchronizer源碼分析
Condition接口ConditionObeject實現Condition接口,一般看一個類實現的接口可以看出它的目的,其實也是熟悉API.
Condition的目的主要是替代Object的wait,notify,notifyAll方法的,它是基于Lock實現的.(而Lock是來替代synchronized方法).
public interface Condition { /** * 暫停此線程直至一下四種情況發生 * 1.此Condition被signal() * 2.此Condition被signalAll() * 3.Thread.interrupt() * 4.偽wakeup * 以上情況.在能恢復方法執行時,當前線程必須要能獲得鎖 */ void await() throws InterruptedException; //跟上面類似,不過不響應中斷 void awaitUninterruptibly(); //帶超時時間的await() long awaitNanos(long nanosTimeout) throws InterruptedException; //帶超時時間的await() boolean await(long time, TimeUnit unit) throws InterruptedException; //帶deadline的await() boolean awaitUntil(Date deadline) throws InterruptedException; //喚醒某個等待在此condition的線程 void signal(); //喚醒所有等待在此condition的所有線程 void signalAll(); }AQS中的ConditionObject
此類的構造方法沒有參數,所以不用講
整體講下這個ConditionObject的實現,其實其維護兩個隊列,
Condition隊列,表示等待的隊列,其waitStatus=Node.Condition,由firstWaiter和lastWaiter兩個屬性操控.
Sync隊列,表示可以競爭鎖的隊列,這個跟AQS一致,waitStatus=0;
await()方法呢就是把當前線程創建一個Node加入Condition隊列,接著就一致循環查其在不在Sync隊列,如果當前節點在Sync隊列里了,就可以競爭鎖,恢復運行了.
signal()方法就是把某個節點的nextWaiter設為null,再把其從Condition隊列轉到Sync隊列.
具體細節看下面源碼及注釋:
/** * 暫停此線程,直至許可滿足 * 只看沒有中斷和超時的await方法,其它處理中斷和超時的邏輯不care */ public final void awaitUninterruptibly() { Node node = addConditionWaiter(); //釋放當前線程的鎖 int savedState = fullyRelease(node); boolean interrupted = false; //看自己在不在等待隊列,在 while (!isOnSyncQueue(node)) { //為了線程調度,禁用當前的線程,直到許可可用 LockSupport.park(this); if (Thread.interrupted()) interrupted = true; } //獲取剛才釋放的鎖,參考AQS中acquire的講解吧 if (acquireQueued(node, savedState) || interrupted) selfInterrupt(); } /** * 添加一個等待Node到隊列中 */ private Node addConditionWaiter() { Node t = lastWaiter; // 如果尾節點被取消了,清理掉 if (t != null && t.waitStatus != Node.CONDITION) { unlinkCancelledWaiters(); t = lastWaiter; } // 新建一個Condition狀態的節點,并將其加在尾部 Node node = new Node(Thread.currentThread(), Node.CONDITION); if (t == null) firstWaiter = node; else t.nextWaiter = node; lastWaiter = node; return node; } /** * 釋放當前的state,最終還是調用tryRelease方法 */ final int fullyRelease(Node node) { boolean failed = true; try { int savedState = getState(); if (release(savedState)) { failed = false; return savedState; } else { throw new IllegalMonitorStateException(); } } finally { if (failed) node.waitStatus = Node.CANCELLED; } } /** * 是否還需要等待 */ final boolean isOnSyncQueue(Node node) { //如果狀態為Node.CONDITION,即還在Condition隊列中,還得再循環中等待 //如果其waitStatus不為Node.CONDITION,其前置節點,即Sync的前置節點為null,為啥也繼續等著呢???誰來解答我的疑問 if (node.waitStatus == Node.CONDITION || node.prev == null) return false; //如果狀態不為Node.CONDITION,即不在Condition隊列了,有前置節點也有后置節點,那么其一定在Sync隊列 if (node.next != null) return true; /* * 其前置節點為非null,但是也不在Sync也是可能的,因為CAS將其加入隊列失敗.所以我們需要從尾部開始遍歷確保其在隊列 */ return findNodeFromTail(node); } / /** * 從尾部查找node節點 */ private boolean findNodeFromTail(Node node) { Node t = tail; for (;;) { if (t == node) return true; if (t == null) return false; t = t.prev; } }signal()
/** * 釋放信號 */ public final void signal() { //如果不是排它模式,則拋出IllegalMonitorStateException異常 if (!isHeldExclusively()) throw new IllegalMonitorStateException(); //將等待隊列的第一個節點出隊列,并將其加入AQS的鎖隊列 Node first = firstWaiter; if (first != null) doSignal(first); } /** * 真正的釋放信號 */ private void doSignal(Node first) { do { //講first的nextWaiter設為null if ( (firstWaiter = first.nextWaiter) == null) lastWaiter = null; first.nextWaiter = null; } // 如果轉換隊列不成功且等待隊列不為null,繼續do while (!transferForSignal(first) && (first = firstWaiter) != null); } /** * 將一個節點從condition隊列轉換到Sync隊列 */ final boolean transferForSignal(Node node) { //所謂的Condition隊列和Sync隊列就在于waitStatus值 if (!compareAndSetWaitStatus(node, Node.CONDITION, 0)) return false; Node p = enq(node); int ws = p.waitStatus; if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL)) LockSupport.unpark(node.thread); return true; } /** * 喚醒所有等待在此condition的所有線程 */ public final void signalAll() { if (!isHeldExclusively()) throw new IllegalMonitorStateException(); Node first = firstWaiter; if (first != null) doSignalAll(first); } /** * 遍歷所有節點,使其加入到Sync隊列 */ private void doSignalAll(Node first) { lastWaiter = firstWaiter = null; do { Node next = first.nextWaiter; first.nextWaiter = null; transferForSignal(first); first = next; } while (first != null); }
在此輸入正文
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70093.html
摘要:前置文章為,如果不了解的基本和實現機制,建議先看一下這個文章。類似于和,常用于實現生產者消費者。以下代碼是一個用的做的一個生產者消費者例子。 前置文章為https://segmentfault.com/a/11...,如果不了解AQS的基本lock和unlock實現機制,建議先看一下這個文章。 Condition類似于wait和notify,notifyAll,常用于實現生產者消費者。...
摘要:實現原理是通過基于單鏈表的條件隊列來管理等待線程的。中斷在轉移到同步隊列期間或之后發生,此時表明有線程正在調用轉移節點。在該種中斷模式下,再次設置線程的中斷狀態。 1. 簡介 Condition是一個接口,AbstractQueuedSynchronizer 中的ConditionObject內部類實現了這個接口。Condition聲明了一組等待/通知的方法,這些方法的功能與Objec...
摘要:實現原理是通過基于單鏈表的條件隊列來管理等待線程的。中斷在轉移到同步隊列期間或之后發生,此時表明有線程正在調用轉移節點。在該種中斷模式下,再次設置線程的中斷狀態。 1. 簡介 Condition是一個接口,AbstractQueuedSynchronizer 中的ConditionObject內部類實現了這個接口。Condition聲明了一組等待/通知的方法,這些方法的功能與Objec...
摘要:實現原理是通過基于單鏈表的條件隊列來管理等待線程的。中斷在轉移到同步隊列期間或之后發生,此時表明有線程正在調用轉移節點。在該種中斷模式下,再次設置線程的中斷狀態。 1. 簡介 Condition是一個接口,AbstractQueuedSynchronizer 中的ConditionObject內部類實現了這個接口。Condition聲明了一組等待/通知的方法,這些方法的功能與Objec...
摘要:與之相關的方法有三個原子性地修改都是類型,可見我們可以進行,來定義的獲取與釋放從而實現我們自定義的同步器。 前言 源碼分析我認為主要有兩個作用:滿足好奇心,我想每一個有追求的人都不會滿足于僅僅做一個API Caller實現功能就好,我們也想知道它到底是怎么實現的;借鑒與升華,當我們明白了一個類的設計原理,在一定的情境下我們可以借鑒其設計哲學,甚至針對我們自己特殊的業務場景對其進行改良與...
閱讀 1617·2021-11-22 14:45
閱讀 1063·2021-11-17 09:33
閱讀 3322·2021-09-02 09:48
閱讀 969·2019-08-30 15:54
閱讀 2767·2019-08-30 15:53
閱讀 2553·2019-08-30 12:54
閱讀 2241·2019-08-29 12:37
閱讀 2421·2019-08-26 13:58