java并发源码:Condition

java并发源码:Condition

比对Object的监视器方法和Condition接口

对比项ObjectCondition
前置条件获取对象的锁调用Lock.lock()获取锁 调用Lock.newCondition()获取condition对象。
调用方式直接调用直接调用
等待队列个数1个多个
当前线程释放锁并进入等待状态支持支持
当前线程释放锁并进入等待状态,在等待状态中不响应中断不支持支持
当前线程释放锁并进入超时等待状态支持支持
当前线程释放锁并进入等待状态到将来的某个时间不支持支持
唤醒等待队列中的一个线程支持支持
唤醒等待队列中的全部线程支持支持

Condition对象是依赖Lock对象的。

API方法

方法名称描述
void await()当前线程进入等待状态知道被通知或中断,当前线程将进入运行状态且从await()方法返回的情况: 1其它线程中断当前线程 2如果当前等待线程从await()返回,则表明该线程已经获取了Condition对象所对应的锁。
void awaituninterruptibly()当前线程进入等待状态直到被通知,从方法名称上可以看出该方法对中断不敏感。
long awaitNanos(long nanosTimeout)当前线程进入等待状态直到被通知,中断或者超时。返回值表示剩余的时间,如果在nanosTimeout纳秒之前被唤醒,那么返回值就是(nanosTimeout-实际耗时)。如果返回值是0或者负数,那么可以认定已经超时。
boolean awaitUntil(Date deadli)当前线程进入等待状态直到被通知,中断或者直到某个时间,如果没有到指定时间就被通知,方法返回true,否则到了指定时间,方法返回false
void signal()唤醒一个等待在Condition的线程,该线程从等待方法返回前必须获得与Condition相关联的锁。
void signalAll()唤醒所有等待在Condition的线程,能够从等待方法返回的线程必须获得与Condition相关联的锁。

实现分析

等待队列:

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

​ 一个对象拥有一个同步队列和等待队列。

​ Lock(同步器)拥有一个同步队列和多个等待队列。

等待

ConditionObject的await方法。

public final void await() throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
  	//当前线程加入等待队列
    Node node = addConditionWaiter();
  	//释放同步状态,也就是释放锁。
    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);
}

调用await()方法,相当于从同步队列的首节点(获取了锁的节点)移动到Condition的等待队列中。

通知
public final void signal() {
    if (!isHeldExclusively())
        throw new IllegalMonitorStateException();
    Node first = firstWaiter;
    if (first != null)
        doSignal(first);
}
private void doSignal(Node first) {
    do {
        if ( (firstWaiter = first.nextWaiter) == null)
            lastWaiter = null;
        first.nextWaiter = null;
    } while (!transferForSignal(first) &&
             (first = firstWaiter) != null);
}
final boolean transferForSignal(Node node) {
    /*
     * If cannot change waitStatus, the node has been cancelled.
     */
    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;
}

​ 当前线程必须是获取了锁的线程,接着获取等待队列的首节点,将其移动到同步队列并使用LockSupport唤醒节点中的线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值