Condition等待通知

一、介绍

condition接口提供了类似Object的监视器的方法,用来实现等待通知模式。但是与Object监视器又有一定的区别,与不同。主要体现在;

  • 等待队列
    • Obejct模式 :一个
    • Condition:多个
  • 等待超时模式
    • Object模式:不支持
    • Condition模式:支持
二、使用方法
// 声明锁的对象
ReentrantLock lock = new ReentrantLock();
// 获取监视器
Condition condition = lock.newCondition();

// 获取锁
lock.lock();

// 等待
condition.await();
//通知    
condition.signal();

//释放锁
lock.unlock();

当调用await()方法之后,当前线程会释放锁并在此等待,其他线程调用Condition对象signal()方法,通知当前线程后,当前线程才从await()返回,但是返回对前提也就是需要获得锁。

三、源码解析

每一个Condition对象包含一个等待队列,该队列是Condition实现的关键,用来实现等待/通知的功能。在Condition中可以拥有多个等待队列。

  • 调用await()方法加入等待队列
  • 调用signal()方法 从等待队列中移出,加入同步队列开始锁的获取
3.1 等待

当调用await方法时,当前线程会进入等待队列,并且释放锁,线程状态会变为等待状态(CONDITION :-2);当调用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;
            }

            // 唤醒同步队列中到后继节点;node节点开始自旋获取
            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                interruptMode = REINTERRUPT;
            if (node.nextWaiter != null) // clean up if cancelled
                unlinkCancelledWaiters();
            if (interruptMode != 0)
                reportInterruptAfterWait(interruptMode);
        }
3.2 通知

调用Condition的signal()方法,会唤醒在等待队列中等待时候最长的节点,然后移动到同步队列当中。

         
public final void signal() {
    // 判断当前线程释放获取锁
    if (!isHeldExclusively())
        throw new IllegalMonitorStateException();

    Node first = firstWaiter;
    if (first != null)
        /**
             * 从等待队列中移出 并且添加到同步队列当中
             */
        doSignal(first);
}

当执行了doSignal方法后,当前线程从等待队列中移除,await方法中将继续执行,调用acquireQueued(node),内部进行自旋获取锁,获取锁当条件:

  • 1、前节点是头节点
  • 2、获取到同步状态
四、小结

condition可以用来实现**等待/通知模式。**具体实现逻辑是,等待的线程await加入等待队列,当被通知后,从等待队列中移出,添加到同步队列中,然后继续开始锁到获取(自旋获取)

五、参考

《并发编程的艺术》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值