Condition

1、概述
任意一个Java对象都拥有一组监视器方法(定义在java.lang.Object上),主要包括wait()、wait(long timeout)、notify()以及notifyAll()方法,与synchronised同步关键字配合,可以实现等待/通知模式。

Condition接口也提供了类似Object的监视器方法,与Lock配合,也可以实现等待/通知模式。

主要区别:Object只有一个等待队列,Condition允许多个等待队列。

2、原理分析

ConditionObject是Condtion的实现类,也是AbstractQueuedSynchronizer的内部类。即Condition实现的是同步器的内部类,因此每个Condition的实例都能访问同步器方法。

Object的监视器模型,一个对象有一个同步队列和一个等待队列;
而同步器拥有一个同步队列和多个等待队列。

1)等待

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的等待队列中。

2)通知

public final void signal() {
    // 判断当前线程是否获取了锁
    if (!isHeldExclusively())
        throw new IllegalMonitorStateException();
    Node first = firstWaiter;
    if (first != null)
        doSignal(first);
}

首先检查当前线程是否获取了锁,获取锁之后,则调用同步器的enq(Node node) 方法,将等待队列的首节点(等待队列中等待时间最长的点)线程安全地移动到同步队列中,并使用LockSupport唤醒节点中的线程。

唤醒之后,将从await()方法的while循环中退出,进而调用同步器的acquireQueued()方法,加入到获取同步状态的竞争中。

Condition的signalAll()方法,相当于等待队列中的每个节点执行一次signal()方法,效果就是将等待队列中的所有节点全部移到同步队列中,并唤醒每个节点的线程。

3、LockSupport工具类

LockSupport定义一组公共静态方法,如park()、unpark()等,提供最基本的线程阻塞和唤醒功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值