1. 程式人生 > 實用技巧 >AQS 中的條件

AQS 中的條件

按照我看原始碼的進度,條件 condition 是 aqs 的最後一塊拼圖。

我總結的 aqs 三要素:
state
ownerThread
等待佇列

這裡沒有考慮到 condition,condition 的用法如下

lock.lock();
  condition.await(t);

lock.unlock();

藉助 AbstractQueuedSynchronizer.ConditionObject#await(long, java.util.concurrent.TimeUnit)
來分析條件佇列,這個方法會掛起執行緒,一段時間後自動醒來,不需要其他執行緒喚醒。

await(t) 要做哪些事?

整體來看,要做兩件事:
一、釋放鎖,掛起執行緒
二、當執行緒醒來,重新獲取鎖

細分步驟:

1. 只有持有了鎖,才能做 await(t)
2. 把當前執行緒加入到條件佇列中
3. 重置 state 值為 0,並喚醒等待佇列中的節點(這個動作其實就是釋放鎖)
4. 不考慮自旋時間,直接掛起執行緒 t 時間
5. 等待 t 時間後,執行緒被 os 喚醒,把執行緒所在的節點從條件佇列取出,放入等待佇列,執行緒需要重新獲取鎖

// java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject#await(long, java.util.concurrent.TimeUnit)
public final boolean await(long time, TimeUnit unit) throws InterruptedException { long nanosTimeout = unit.toNanos(time); if (Thread.interrupted()) throw new InterruptedException(); Node node = addConditionWaiter(); int savedState = fullyRelease(node); final long
deadline = System.nanoTime() + nanosTimeout; boolean timedout = false; int interruptMode = 0; while (!isOnSyncQueue(node)) { if (nanosTimeout <= 0L) { timedout = transferAfterCancelledWait(node); break; } if (nanosTimeout >= spinForTimeoutThreshold) LockSupport.parkNanos(this, nanosTimeout); if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) break; nanosTimeout = deadline - System.nanoTime(); } if (acquireQueued(node, savedState) && interruptMode != THROW_IE) interruptMode = REINTERRUPT; if (node.nextWaiter != null) unlinkCancelledWaiters(); if (interruptMode != 0) reportInterruptAfterWait(interruptMode); return !timedout; }