`

Condition&(wait,notify)

 
阅读更多

Condition.await和Object.wait 

我们发现 ArrayBlockingList 并没有使用 Object.wait ,而是使用的 Condition.await ,这是为什么呢?其中又有哪些原因呢?

Condition 对象可以提供和 Object 的 wait 和 notify 一样的行为,但是后者必须使用 synchronized 这个内置的monitor锁,而 Condition 使用的是 RenentranceLock 。这两种方式在阻塞等待时都会将相应的锁释放掉,但是 Condition 的等待可以中断,这是二者唯一的区别。

 

[转载的源码分析]

public final void await() throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    //在condition wait队列上添加新的节点
    Node node = addConditionWaiter();
    //释放当前持有的锁
    int savedState = fullyRelease(node);
    int interruptMode = 0;
    //由于node在之前是添加到condition wait queue上的,现在判断这个node
    //是否被添加到Sync的获得锁的等待队列上。
    //node在condition queue上说明还在等待事件的notify,
    //notify函数会将condition queue 上的node转化到Sync的队列上。
    while (!isOnSyncQueue(node)) {
        //node还没有被添加到Sync Queue上,说明还在等待事件通知
        //所以调用park函数来停止线程执行
        LockSupport.park(this);
        //判断是否被中断,线程从park函数返回有两种情况,一种是
        //其他线程调用了unpark,另外一种是线程被中断
        if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
            break;
    }
    //代码执行到这里,已经有其他线程调用notify函数,或则被中断,该线程可以继续执行,但是必须先
    //再次获得调用await函数时的锁.acquireQueued函数在AQS文章中做了介绍.
    if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
         reportInterruptAfterWait(interruptMode); //
   ....
}

 

 

signal 函数将等待事件最长时间的线程节点从等待condition的队列移动到获得lock的等待队列中.

public final void signal() {
    //
    if (!isHeldExclusively())
    //如果当前线程没有获得锁,抛出异常
        throw new IllegalMonitorStateException();
    Node first = firstWaiter;
    if (first != null)
        //将Condition wait queue中的第一个node转移到acquire lock queue中.
        doSignal(first);
}

private void doSignal(Node first) {
    do {
   //由于生产者的signal在有消费者等待的情况下,必须要通知
        //一个消费者,所以这里有一个循环,直到队列为空
        //把first 这个node从condition queue中删除掉
        //condition queue的头指针指向node的后继节点,如果node后续节点为null,那么也将尾指针也置为null
        if ( (firstWaiter = first.nextWaiter) == null)
            lastWaiter = null;
        first.nextWaiter = null;
    } while (!transferForSignal(first) &&
             (first = firstWaiter) != null);
    //transferForSignal将node转而添加到Sync的acquire lock 队列
}

final boolean transferForSignal(Node node) {
    //如果设置失败,说明该node已经被取消了,所以返回false,让doSignal继续向下通知其他未被取消的node
    if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
        return false;
    //将node添加到acquire lock queue中.
    Node p = enq(node);
    int ws = p.waitStatus;
    //需要注意的是这里的node进行了转化
    //ws>0代表canceled的含义所以直接unpark线程
    //如果compareAndSetWaitStatus失败,所以直接unpark,让线程继续执行await中的
    //进行isOnSyncQueue判断的while循环,然后进入acquireQueue函数.
    //这里失败的原因可能是Lock其他线程释放掉了锁,同步设置p的waitStatus
    //如果compareAndSetWaitStatus成功了呢?那么该node就一直在acquire lock queue中
    //等待锁被释放掉再次抢夺锁,然后再unpark
    if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
        LockSupport.unpark(node.thread);
    return true;
}

 

 

分享到:
评论

相关推荐

    java中的Lock类和Condition类.docx

    之前已经说道,JVM提供了synchronized关键字来实现对变量的同步访问以及用wait和notify来实现线程间通信。在jdk1.5以后,JAVA提供了Lock类来实现和synchronized一样的功能,并且还提供了Condition来显示线程间通信。...

    基础技术部牛路《Java多线程入阶分享》纯干货

    4.线程间通信:lock、condition、wait、notify、notifyAll 5.Lock-free:atomic、concurrentMap.putIfAbsent、CopyOnWriteArrayList 6.关于锁的经验介绍 7.并发流程控制手段:CountDownLatch、Barrier 8.定时器:...

    阿里Java并发程序设计教程

    4、线程间的协调手段:lock、condition、wait、notify、notifyAll ☆ ☆ ☆ 5、Lock-free: atomic、concurrentMap.putIfAbsent、CopyOnWriteArrayList ☆ ☆ ☆ 6、关于锁使用的经验介绍 7、并发流程控制手段:...

    Java并发程序设计教程

    4、线程间的协调手段:lock、condition、wait、notify、notifyAll☆☆☆ 5、Lock-free: atomic、concurrentMap.putIfAbsent、CopyOnWriteArrayList☆☆☆ 6、关于锁使用的经验介绍 7、并发流程控制手段:...

    Java编程并发程序设计

    4、线程间的协调手段:lock、condition、wait、notify、notifyAll☆☆☆ 5、Lock-free: atomic、concurrentMap.putIfAbsent、CopyOnWriteArrayList☆☆☆ 6、关于锁使用的经验介绍 7、并发流程控制手段:...

    Java并发编程原理与实战

    使用Condition重写waitnotify案例并实现一个有界队列.mp4 深入解析Condition源码.mp4 实战:简易数据连接池.mp4 线程之间通信之join应用与实现原理剖析.mp4 ThreadLocal 使用及实现原理.mp4 并发工具类...

    java多线程系列(四)ReentrantLock的使用.docx

    创建多个condition对象 ...Condition类的awiat方法和Object类的wait方法等效 Condition类的signal方法和Object类的notify方法等效 Condition类的signalAll方法和Object类的notifyAll方法等效

    Python多线程编程(七):使用Condition实现复杂同步

    Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方法。 使用Condition的主要方式为:线程首先acquire一个条件变量,然后判断一些条件。如果条件不满足则wait;如果条件...

    python多线程高级锁condition简单用法示例

    – wait:线程挂起,收到notify通知后继续运行 – notify:通知其他线程, 解除其它线程的wai状态 – notifyAll(): 通知所有线程 – acquire和release: 获得锁和解除锁, 与lock类似, – enter和exit使得对象支持上...

    Python线程条件变量Condition原理解析

    这篇文章主要介绍了Python线程条件变量Condition原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的...wait() 会释放这个锁,阻塞本线程直到其他线程通过 notify() 或 notify_all() 来唤醒它。

    Python threading模块condition原理及运行流程详解

    如果条件满足,进行一些处理改变条件后,通过notify方法通知其他线程,其他处于wait状态的线程接到通知后会重新判断条件。 不断的重复这一过程,从而解决复杂的同步问题。 Condition的基本原理如下: 可以认为...

    这就是标题—— JUC.pdf

    wait()、notify()和notifyAll() 虚假唤醒 Condition 定制化通信 多线程锁 并发下的集合类 List Set Map Callable接口 线程创建的方式 callable / runnable FutureTask JUC常用辅助类 CountDownLatch (减少计数器) ...

    python条件变量之生产者与消费者操作实例分析

    Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方法。线程首先acquire一个条件变量,然后判断一些条件。如果条件不满足则wait;如果条件满足,进行一些处理改变条件后...

    Java中的Runnable接口最全讲义

    7.1 使用wait()和notify()方法 7.2 使用Lock和Condition 8. 线程池: 8.1 线程池的概述 8.2 使用Executor框架创建线程池 8.3 线程池的优势和适用场景 9. 线程中断: 9.1 如何中断线程 9.2 处理中断请求 10. 线程状态...

    python 多线程的同步机制 以python2例程的方式讲解了python 多线程的同步 常用的方法,主要是锁、条件同步、队列

    python 多线程的同步机制 以python2例程的方式讲解了python 多线程的同步 常用的方法,主要是锁、条件同步、队列 ... 保证每一个wait()方法调用都有一个相对应的notify()调用,当然也可以调用notifyAll()方法以

    并发编程示例,涉及到AtomicXXX、CountDownLatch、线程池等

    并发编程的一些小示例 1.等待通知的几种方式,包括Object的wait/notify,Condition的await/signal 2. CountDownLatch,统一控制多线程开始和结束 3.原子操作,AtomicXXX 4.线程池

    JAVA多线程实现2个producer和一个Consumer把整数放入到一个环形缓冲Circle Buffer中

    采用同步机制synchronized/wait(notify)或者lock(unlock)/condition variable实现两个producer和一个consumer之间协调运行。运行结果输出格式为:Put(or Get) number {[content] length start_index end_index} 包含...

    Java并发编程基础.pdf

    线程同步与通信:掌握Java中的同步机制,如synchronized关键字、wait()和notify()方法,以及更高级的并发工具如ReentrantLock、Condition等。了解线程间的通信方式,如共享内存、消息传递等。 并发集合:熟悉Java...

    龙果 java并发编程原理实战

    第32节使用Condition重写wait/notify案例并实现一个有界队列00:22:05分钟 | 第33节深入解析Condition源码00:21:15分钟 | 第34节实战:简易数据连接池00:24:53分钟 | 第35节线程之间通信之join应用与实现原理剖析...

Global site tag (gtag.js) - Google Analytics