美文网首页
Condition的实现

Condition的实现

作者: kindol | 来源:发表于2018-08-02 23:20 被阅读0次

ConditionObject是同步器AQS的内部类,因为Condition的操作需要获取相关联的锁,所以作为同步器的内部类也比较合理。每个Condition对象都包含着一个FIFO队列(等待队列),该队列是Condition对象实现等待/通知的关键。

与object唤醒、等待方法的区别

Object中的wait(),notify(),notifyAll()方法是和"同步锁"(synchronized关键字)捆绑使用的;而Condition是需要与"互斥锁"/"共享锁"捆绑使用的。

等待队列

FIFO,每个节点都包含了一个线程引用,该线程就是在Condition对象上等待的线程,如果一个线程调用了await()方法,该线程就会释放锁、构造成节点进入等待队列并进入等待状态。

Object的监视器模型上,一个对象拥有一个同步队列和等待队列,而Lock(同步器)拥有一个同步队列和多个等待队列

A12.png

await()

使当前线程进入等待队列并释放锁,同时线程状态变为等待状态。

从队列的角度来看,相当于同步队列的首节点(获取了锁的节点)移动到Condition的等待队列中。

+ View code
public final void await() throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    // 添加至等待队列中
    Node node = addConditionWaiter();
    // 释放同步状态,释放锁
    long 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);
}

调用此方法的线程已经有锁,即是同步队列的首节点,该方法将会将当前线程构造节点并加入等待队列,然后释放同步状态,唤醒同步队列中的后继节点,然后当前线程会进入等待状态。

当等待队列中的节点被唤醒,则唤醒节点的线程开始尝试获取同步状态,如果不是通过其他线程调用Condition.signal()方法唤醒,而是进行中断,将会抛出异常

通知

调用此方法的前置条件是当前线程必须获取了锁,可以看到signal()进行了isHeldExclusively()检查

调用Condition的signal(),将会唤醒等待队列的首节点,然后将其移到同步队列(使用enq确保移动到了同步队列)

被唤醒后的线程,将从await()方法中的while循环中退出,在同步队列中自旋

signalAll()则是相当于每个等待队列的线程都调用了一次signal()

相关文章

网友评论

      本文标题:Condition的实现

      本文链接:https://www.haomeiwen.com/subject/cceevftx.html