JUC虚假唤醒(六)
为什么条件锁会产生虚假唤醒现象(spurious wakeup)?
在不同的语言,甚至不同的操作系统上,条件锁都会产生虚假唤醒现象。所有语言的条件锁库都推荐用户把wait()放进循环里:
while (!cond) {
lock.wait();
}
这个一般出现在多线程竞争的时候,when no thread specifically broadcast or signaled that condition variable,也就是没有线程这时候释放锁信号,但是wait也会又返回。(看起来这个属于线程的系统问题,属于几率问题)
如果你采用if的形式的话,就直接往下跑了。
if (!cond) {
lock.wait();
}
产生了虚假唤醒图示说明:

程序说明:
(1)product <= 0时,两个消费者先后根据if条件判断为“缺货”,都进入wait状态;
(2)另外一个生产者生产了产品之后,通过this.notifyAll();的调用,唤醒了所有的消费线程。使得他们共同执行--produce的操作;也就是说,
--product; // 被执行了两次
但是如果你采用while,他会判别你的锁条件标志还没有被修改,那么会再一次的进入到await的状态中。
这个问题其实很好理解
从wait函数中返回的条件有二,根据顺序为
A,从挂起状态中被唤醒
B,获得cond的锁
如果条件变量被notify,有多个线程同时同时从挂起状态中被唤醒,此时他们会争夺cond的锁。
第一个成功获得锁的线程在临界区中读取cond,并决定是继续wait,还是执行他的工作,选择后者可能会修改cond的状态。
因此,后续获得锁的线程必须确认前面的线程是否修改了cond。notify_one和notify_all,分别对应所有的线程都在等同一个cond或存在多个cond关联到同一个条件变量上。与try_lock不同,条件变量很好地解决了线程的等待问题,不用频繁地争夺锁。
wait, notify, notifyAll 方法说明:
- wait:在其他线程调用此对象的 notify()方法或notifyAll()方法前,导致当前线程等待。当前线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用notify方法,或 notifyAll方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行。
- notify:唤醒在此对象监视器上等待的单个线程,直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程,选择是任意性的,被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争。
- notifyAll:唤醒在此对象监视器上等待的所有线程,直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争。
参考链接
本文主要整理自互联网,主要是便于自己复习知识所用,侵权联系删除,以下为原文参考链接!
【1】为什么条件锁会产生虚假唤醒现象(spurious wakeup)?
【2】JUC 源码分析 四 wait notify notifyAll 与 条件对象
JUC虚假唤醒(六)的更多相关文章
- (三)juc高级特性——虚假唤醒 / Condition / 按序交替 / ReadWriteLock / 线程八锁
8. 生产者消费者案例-虚假唤醒 参考下面生产者消费者案例: /* * 生产者和消费者案例 */ public class TestProductorAndConsumer { public stat ...
- 7.JUC线程高级-生产消费问题&虚假唤醒
描述 生产消费问题在java多线程的学习中是经常遇到的问题 ,多个线程共享通一个资源的时候会出现各种多线程中经常出现的各种问题. 实例说明 三个类:售货员Clerk,工厂Factory,消费者Cons ...
- java多线程 生产者消费者案例-虚假唤醒
package com.java.juc; public class TestProductAndConsumer { public static void main(String[] args) { ...
- java多线程之消费生产模型-使用synchronized解决虚假唤醒
package com.wenshao.juc; /** * 生产者和消费者案例 * * @author Administrator * */ public class TestProductorAn ...
- Java并发编程虚假唤醒问题(生产者和消费者关系)
何为虚假唤醒: 当一个条件满足时,很多线程都被唤醒了,但是只有其中部分是有用的唤醒,其它的唤醒都是无用功:比如买货:如果商品本来没有货物,突然进了一件商品,这是所有的线程都被唤醒了,但是只能一个人买, ...
- notify丢失、虚假唤醒
notify丢失: 假设线程A因为某种条件在条件队列中等待,同时线程B因为另外一种条件在同一个条件队列中等待,也就是说线程A/B都被同一个Object.wait()挂起,但是等待的条件不同. 现在假设 ...
- pthread_cond_wait虚假唤醒
pthread_cond_wait中的while()不仅仅在等待条件变量前检查条件cond_is_false是否成立,实际上在等待条件变量后也检查条件cond_is_false是否成立.在多线程等待的 ...
- Java-JUC(八):使用wait,notify|notifyAll完成生产者消费者通信,虚假唤醒(Spurious Wakeups)问题出现场景,及问题解决方案。
模拟通过线程实现消费者和订阅者模式: 首先,定义一个店员:店员包含进货.卖货方法:其次,定义一个生产者,生产者负责给店员生产产品:再者,定义一个消费者,消费者负责从店员那里消费产品. 店员: /** ...
- 多线程编程中条件变量和的spurious wakeup 虚假唤醒
1. 概述 条件变量(condition variable)是利用共享的变量进行线程之间同步的一种机制.典型的场景包括生产者-消费者模型,线程池实现等. 对条件变量的使用包括两个动作: 1) 线程等待 ...
随机推荐
- gogs仓库管理软件 exec: "git-upload-pack": executable file not found in $PATH
当配置完个人中心的ssh公钥的时候,在客户端拉取代码的时候,提示如下错误: Cloning into 'comix-b2m'... Gogs: Internal error fatal: Could ...
- Libinput 1.13 RC2发布
Red Hat的Peter Hutterer周四宣布发布libinput 1.13 RC2,作为X.Org和Wayland Linux系统使用此输入处理库的最新测试版本. Libinput 1.13将 ...
- linux内存源码分析 - 伙伴系统(释放页框)
本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 翻了一下之前的文章,发现竟然忘记写内核是如何释放页框的,罪过. 释放页框很简单,其实只有几步 检查此页是否被其他 ...
- face detection[Face R-CNN]
face r-cnn是腾讯ai实验室的作品,而且登录过腾讯ai实验室官网,发现果然硕果累累,不得不佩服. 1 引言 人脸检测虽然相对之前有了不小的进步,可是还是因为真实世界中人脸图像的明显变化导致仍然 ...
- Visual Studio 2012 与此版本的 Windows 不兼容。有关详细信息,请联系 Microsoft
参考网址:Visual Studio 2012 与此版本的 Windows 不兼容 解决 下载更新包安装:http://www.microsoft.com/zh-CN/download/details ...
- Web组件流畅拖动效果
拖动效果,可以形象的帮助用户处理一些问题,比如Windows删除文件,只需将文件拖动至回收站即可.比起右键显得更形象,我觉得更好玩一点^_^.当然,在其他许多方面,其实也有用到拖动效果,只是他们不是那 ...
- Maven学习第3期---m2eclipse使用
一.m2eclipse简介 和Nexus一样,m2eclipse也是Sonatype出品的一款开源工具,它基于Eclipse Public License-v.10开源许可证发布,用户可以免费下载并使 ...
- 百度智能手环方案开源(含源码,原理图,APP,通信协议等)
分享一个百度智能手环开源项目的设计方案资料. 项目简介 百度云智能手环的开源方案是基于Apache2.0开源协议,开源内容包括硬件设计文档,原理图.ROM.通讯协议在内的全套方案,同时开放APP和云服 ...
- C#使用Json.Net遍历Json
StringBuilder builder=new StringBuilder(); builder.AppendLine("{"); builder.AppendLine(&qu ...
- redis-trib.rb命令详解
redis-trib.rb是官方提供的Redis Cluster的管理工具,无需额外下载,默认位于源码包的src目录下,但因该工具是用ruby开发的,所以需要准备相关的依赖环境. 准备redis-tr ...