ReentrantLock源码解析之newCondition
上源码
/**
* Returns a {@link Condition} instance for use with this
* {@link Lock} instance.
*(为lock对象返回一个Condition实例)
* <p>The returned {@link Condition} instance supports the same
* usages as do the {@link Object} monitor methods ({@link
* Object#wait() wait}, {@link Object#notify notify}, and {@link
* Object#notifyAll notifyAll}) when used with the built-in
* monitor lock.
*(返回的Condition实例的用法和Object监视器方法Object#wait,Object#notify,Object#notifyAll一样当使 * 用内建的监视锁)
* <ul>
*
* <li>If this lock is not held when any of the {@link Condition}
* {@linkplain Condition#await() waiting} or {@linkplain
* Condition#signal signalling} methods are called, then an {@link
* IllegalMonitorStateException} is thrown.
*(如果这个锁没有被持有当调用其await,signal方法就会抛出IllegalMonitorStateException异常)
* <li>When the condition {@linkplain Condition#await() waiting}
* methods are called the lock is released and, before they
* return, the lock is reacquired and the lock hold count restored
* to what it was when the method was called.
*(当condition的await方法被调用,当前线程就会释放锁,在他们返回之前,这个锁被重新获取然后锁的引用计数重新存 * 储和方法调用时一样)
* <li>If a thread is {@linkplain Thread#interrupt interrupted}
* while waiting then the wait will terminate, an {@link
* InterruptedException} will be thrown, and the thread's
* interrupted status will be cleared.
*(如果线程被打断当等待状态然后等待将被终止,InterruptedException将被抛出,同时线程的中断状态将被清除)
* <li> Waiting threads are signalled in FIFO order.
*(等待的线程将按FIFO的顺序唤醒)
* <li>The ordering of lock reacquisition for threads returning
* from waiting methods is the same as for threads initially
* acquiring the lock, which is in the default case not specified,
* but for <em>fair</em> locks favors those threads that have been
* waiting the longest.
*(从等待状态恢复后获取锁的顺序和线程初始获取锁时的顺序是一样的,默认的实例没有被规定,但是对于公平锁,则更倾向 * 于等待时间最长的)
* </ul>
*
* @return the Condition object
* 返回 Condition 实例
*/
public Condition newCondition() {
return sync.newCondition();
}
实现调用的是sync的newCondition方法
final ConditionObject newCondition() {
return new ConditionObject();
}
最终返回的是AQS(AbstractQueuedSynchronizer)的ConditionObject对象
下面来分析一下Condition的实现类ConditionObject对的await和signal实现
Condition.await
/**
* Implements interruptible condition wait.
*(可中断的condition wait实现)
* <ol>
* <li> If current thread is interrupted, throw InterruptedException.
*(如果当前线程被中断,抛出InterruptedException异常)
* <li> Save lock state returned by {@link #getState}.
*(存储lock状态通过getState返回)
* <li> Invoke {@link #release} with saved state as argument,
* throwing IllegalMonitorStateException if it fails.
*
* <li> Block until signalled or interrupted.
*(阻塞直到被signal唤醒或者被中断)
* <li> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
* <li> If interrupted while blocked in step 4, throw InterruptedException.
* </ol>
*/
public final void await() throws InterruptedException {
//线程中断检测
if (Thread.interrupted())
throw new InterruptedException();
//①新增Condition Waiter节点
Node node = addConditionWaiter();
//②释放当前节点 并保存释放前的state状态
int savedState = fullyRelease(node);
int interruptMode = 0;
//③判断该节点在不在同步队列
while (!isOnSyncQueue(node)) {
//如果不在的话 阻塞当前线程
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
//尝试获取锁
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
step①:ConditionObject#addConditionWaiter 作用就是新增一个condition节点到等待队列,这个队列不是AQS里的队列,是ConditionObject内维护的一个Condition状态的队列
/**
* Adds a new waiter to wait queue.
* @return its new wait node
*/
private Node addConditionWaiter() {
Node t = lastWaiter;
// If lastWaiter is cancelled, clean out.
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;
}
step② ConditionObject#fullyRelease
/**
* Invokes release with current state value; returns saved state.
* Cancels node and throws exception on failure.
* @param node the condition node for this wait
* @return previous sync state
*/
final int fullyRelease(Node node) {
boolean failed = true;
try {
int savedState = getState();
//释放掉当前的锁 将state重置为0
if (release(savedState)) {
failed = false;
return savedState;
} else {
throw new IllegalMonitorStateException();
}
} finally {
if (failed)
node.waitStatus = Node.CANCELLED;
}
}
step③:AQS#isOnSyncQueue
/**
* Returns true if a node, always one that was initially placed on
* a condition queue, is now waiting to reacquire on sync queue.
*(返回true如果一个节点被初始化在condition队列上,现在在同步队列上等待重新获取锁)
* @param node the node
* @return true if is reacquiring
*/
final boolean isOnSyncQueue(Node node) {
if (node.waitStatus == Node.CONDITION || node.prev == null)
return false;
if (node.next != null) // If has successor, it must be on queue
return true;
/*
* node.prev can be non-null, but not yet on queue because
* the CAS to place it on queue can fail. So we have to
* traverse from tail to make sure it actually made it. It
* will always be near the tail in calls to this method, and
* unless the CAS failed (which is unlikely), it will be
* there, so we hardly ever traverse much.
*(节点的前继节点是非空的,但还没有进入队列,因为CAS将其放入队列可能会失败。所以我们不得不从尾节点开始反 * 向查找节点是否存在。除非cas失败,它将在这里,所以我们几乎不反向查找))
*/
return findNodeFromTail(node);
}
Condition.signal
ConditionObject#signal
/**
* Moves the longest-waiting thread, if one exists, from the
* wait queue for this condition to the wait queue for the
* owning lock.
* 移除等待时间最长的线程,如果存在将其从condition队列移动到aqs队列去获取锁
* @throws IllegalMonitorStateException if {@link #isHeldExclusively}
* returns {@code false}
*/
public final void signal() {
//当前线程必须占用锁,否则抛出异常
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
//第一个节点
Node first = firstWaiter;
if (first != null)
//通知第一个节点
doSignal(first);
}
ConditionObject#doSignal
/**
* Removes and transfers nodes until hit non-cancelled one or
* null. Split out from signal in part to encourage compilers
* to inline the case of no waiters.
* @param first (non-null) the first node on condition queue
*/
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
//去除当前节点
first.nextWaiter = null;
//transferForSignal 将当前节点转移到同步队列
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
}
AQS#transferForSignal
/**
* Transfers a node from a condition queue onto sync queue.
* Returns true if successful.
* @param node the node
* @return true if successfully transferred (else the node was
* cancelled before signal)
*/
final boolean transferForSignal(Node node) {
/*
* If cannot change waitStatus, the node has been cancelled.
*/
//节点状态如果不能被转换成0,说该节点以及被取消了
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
/*
* Splice onto queue and try to set waitStatus of predecessor to
* indicate that thread is (probably) waiting. If cancelled or
* attempt to set waitStatus fails, wake up to resync (in which
* case the waitStatus can be transiently and harmlessly wrong).
*/
//将当前节点放入同步队列
Node p = enq(node);
int ws = p.waitStatus;
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
这里可以看到signal并不会直接唤醒Condition队列里的节点线程,而是将该节点转移到aqs内的同步队列,最后通过unlock()方法唤醒同步队列里的节点线程