`

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;
}

 

 

分享到:
评论

相关推荐

    主线程去控制子线程wait与notify

    condition) wait()`来避免“虚假唤醒”问题,即使在没有被唤醒的情况下,线程也会再次检查条件。 在名为`MyTest`的代码文件中,我们可以找到具体的实现示例。这个文件很可能是包含了测试代码,用来演示如何通过主线...

    wait,notify等线程知识.pdf

    通过使用wait()、notify()和notifyAll(),或者Lock和Condition,开发者可以控制线程的执行顺序,确保共享资源的安全访问。 7. **死锁和活锁问题**: 使用wait/notify机制时,需要注意死锁和活锁问题。死锁发生在两...

    详解Java程序并发的Wait-Notify机制

    Java程序并发的Wait-Notify机制是Java多线程编程中的一种重要同步工具,它允许线程之间通过共享对象进行通信和协作。这个机制基于Java的内置锁(也称为监视器锁),通常与`synchronized`关键字一起使用。在Java中,`...

    一家三口共用同一账户银行卡,wait();notify();

    在给定的代码示例中,我们看到了一个模拟家庭共享同一银行账户的场景,通过使用Java多线程的wait()和notify()方法来控制不同线程(代表家庭成员)的操作顺序。这里涉及到的关键知识点包括: 1. **Java多线程**:...

    condition_variable源码以及详细分析.docx

    Condition_Variable 的 wait() 函数使用 pthread_cond_wait() 函数来实现等待操作,而 notify_one() 和 notify_all() 函数使用 pthread_cond_signal() 和 pthread_cond_broadcast() 函数来实现通知操作。 Condition...

    Java wait和notify虚假唤醒原理

    在这个例子中,`condition`是线程等待的条件,`object`是调用`wait()`和`notify()`的对象。当条件不满足时,线程进入等待状态,直到其他线程改变了条件并唤醒它。使用`while`循环可以确保线程在条件满足时才会继续...

    Java的wait(), notify()和notifyAll()使用心得

    `Condition`接口提供了类似`wait()`, `notify()`, `notifyAll()`的功能,但与`Lock`对象关联,提供了更好的可读性和可控性。 总之,`wait()`, `notify()`, 和 `notifyAll()` 在Java多线程编程中扮演着核心角色,...

    Java线程中wait,await,sleep,yield,join用法总结.pdf

    public class ThreadWaitNotify { public static void main(String[] args) throws InterruptedException { DemoTest demoTest = new DemoTest(); // 使用线程池异步执行waitTest方法 ExecutorService ...

    Java条件变量的深度应用:使用Condition接口实现同步等待

    在Java的并发编程中,条件变量是一种非常重要的同步工具,它允许线程在某些条件不...而对于简单的同步需求,Object.wait/notify可能更为合适。通过合理使用这些同步工具,我们可以有效地解决并发编程中的线程安全问题。

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

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

    C++11 并发指南五(stdcondition_variable 详解).docx

    std::condition_variable 的 wait 函数将当前线程阻塞,直到另外一个线程在相同的 std::condition_variable 对象上调用了 notification 函数来唤醒当前线程。 notification 函数有两种形式:notify_one() 和 notify_...

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

    Condition对象,也被称作条件变量,它不仅包含了与锁(Lock)相似的acquire()和release()方法,而且额外提供了wait()和notify()方法。Condition的作用是在线程之间进行更细粒度的协调和控制。 使用Condition实现...

    Java学习资料-详解Condition的await和signal等待/通知机制

    在Java多线程编程中,`Condition`是Java并发包`java.util.concurrent.locks`中的一个接口,它提供了比`Object`类中的`wait()`、`notify()`和`notifyAll()`更加灵活和强大的线程间通信机制。`Condition`与`Lock`配合...

    Python线程协作threading.Condition实现过程解析

    1. `wait(timeout=None)`:让当前持有锁的线程等待,直到其他线程调用`notify()`或`notify_all()`,或者超时(如果指定了`timeout`参数)。超时后,线程会自动返回,即使没有其他线程唤醒它。 2. `notify()`:唤醒...

    Java concurrency之Condition条件_动力节点Java学院整理

    2. **等待/通知机制**:`Condition`提供了`await()`、`signal()`和`signalAll()`方法,它们类似于`synchronized`块中的`wait()`、`notify()`和`notifyAll()`。但是,`Condition`的这些方法需要在持有相应`Lock`的...

    Java并发程序设计教程

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

    python 条件同步的使用 条件同步:threading.Condition 多线程同步,python2例程

    此外,`Condition` 还提供了 `wait()` 和 `notify()`(以及 `notify_all()`)方法,这些方法允许线程等待条件满足或通知其他等待的线程。 ### 区别 与简单的锁相比,条件同步的主要区别在于它可以指定线程等待的...

    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 并发工具类...

Global site tag (gtag.js) - Google Analytics