按照我看源码的进度,条件 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; }