文章目录

  • 1 现象
  • 2 虚假唤醒

1 现象

这个词的定义来源于JDK的Object#wait()方法的注解

官方API明确的告诉我们,为了防止发生中断错误以及虚假唤醒的问题,我们需要将wait()方法放在while() 循环中使用

synchronized (obj) {while (<condition does not hold>) {obj.wait();}... // Perform action appropriate to condition
}

实际上在我们去常使用Object的wait()(notify,notifyAll) 方法的时候,也必然伴随着如官方文档那样的标准的写法(while),那么,问题来了,什么是虚假唤醒(spurious wakeups)

2 虚假唤醒

虚假唤醒(spurious wakeups)的现象一般是伴随着当另一个持有了锁的线程去notify(或者是notifyAll())的时候,锁等待(状态:Thread.State = WAITING)在wait()方法上的线程会被唤醒,并重新竞争锁,竞争到锁的线程会继续执行wait()方法之后的代码【注意这里不是重新去执行一遍锁方法】

这里我们举一个例子:(该代码示例来源于网站)


static class Buf {private final int MAX = 5;private final ArrayList<Integer> list = new ArrayList<>();synchronized void put(int v) throws InterruptedException {if (list.size() == MAX) {wait();}list.add(v);notifyAll();}synchronized int get() throws InterruptedException {// line 0 if (list.size() == 0) {  // line 1wait();  // line2// line 3}int v = list.remove(0);  // line 4notifyAll(); // line 5return v;}synchronized int size() {return list.size();}
}

假设现在有 A,B 两个线程来执行 get 操作,我们假设如下的步骤发生了:

  1. A 拿到了锁 line 0。

  2. A 发现 size==0, (line 1),然后进入等待,并释放锁 (line 2)。

  3. 此时 B 拿到了锁,line0,发现 size==0,(line 1),然后进入等待,并释放锁 (line 2)。

  4. 这个时候有个线程 C 往里面加了个数据 1,那么 notifyAll 所有的等待的线程都被唤醒了。

  5. AB 重新获取锁,假设又是 A 拿到了。然后他就走到 line 3,移除了一个数据,(line4) 没有问题。

  6. A 移除数据后想通知别人,此时 list 的大小有了变化,于是调用了 notifyAll (line5),这个时候就把 B 给唤醒了,那么 B 接着往下走。

  7. 这时候 B 就出问题了,因为其实此时的竞态条件已经不满足了 (size==0)。B 以为还可以删除就尝试去删除,结果就跑了异常了。

上面的这个现象就是虚假唤醒,在if条件下对于条件的判断,都是会触发虚假唤醒,因为持有锁去notify 唤醒在等待wait()的时候,if条件只会去判断一次,如果不通过while判断的化,实际上对于不满足条件下的唤醒操作都是无效操作。

对于这种问题的解决,按照官方文档的指示:都是通过将if条件修改成while

这也解释了为什么wait() 和notify() 方法一般都是在while(条件变量)代码体内

wait和notify的虚假唤醒(spurious wakeups)相关推荐

  1. 条件变量的虚假唤醒(spurious wakeups)问题

    引言 条件变量是我们常用的同步原语之一,它的正确使用方式一般如下图: 在wait端,我们必须把判断布尔条件和wait()放到while循环中,而不能用if语句,原因是可能会引起虚假唤醒. 那么,究竟什 ...

  2. 多线程并发编程需要注意虚假唤醒Spurious wakeup

    虚假唤醒  Spurious wakeup 如果等待线程在没有通知被调用的情况下唤醒,则称为Spurious wakeup. 解决方案就是: 使用while条件判断,更好的方案是避免使用wait这种低 ...

  3. java中wait和notify的虚假唤醒问题

    前言 本篇博客来自 https://www.cnblogs.com/clover-forever/p/12616869.html 自己在此记录一下,方便日后复习. 虚假唤醒的概念 jdk官方文档解释: ...

  4. [C++11 多线程同步] --- 条件变量的那些坑【条件变量信号丢失和条件变量虚假唤醒(spurious wakeup)】

    1 条件变量的信号丢失 1.1 条件变量的信号丢失场景重现 拿生产者和消费者模型举例,看一段示例代码: #include <iostream> #include <vector> ...

  5. C++条件变量Wait及虚假唤醒

    (1) wait(lock): 调用时即阻塞线程,并且调用lock.unlock() (2) wait(lock, conditions): 调用时检查conditions,如果为false,则阻塞线 ...

  6. java线程打水问题_Java 多线程 wait() 虚假唤醒问题

    本文分享 wait()  的虚假唤醒(Spurious Wakeups)问题,会说明什么是虚假唤醒,以及如何解决. 先看一下相关的 java doc: java doc 说由于中断和虚假唤醒可能会发生 ...

  7. linux虚假唤醒(spurious wakeup)

    1.Linux对虚假唤醒的说明 On a multi-processor, it may be impossible for an implementation of pthread_cond_sig ...

  8. java suprious wakeup_多线程编程中条件变量和的spurious wakeup 虚假唤醒

    1. 概述 条件变量(condition variable)是利用共享的变量进行线程之间同步的一种机制.典型的场景包括生产者-消费者模型,线程池实现等. 对条件变量的使用包括两个动作: 1)线程等待某 ...

  9. java notify唤醒原理_Java wait和notify虚假唤醒原理

    自己在此记录一下,方便日后复习. 虚假唤醒的概念 jdk官方文档解释: 所以说在wait和notify一块使用时,如果使用if作为条件时,会有虚假唤醒的情况发生,所以必须使用while作为循环条件.下 ...

最新文章

  1. js 浅拷贝直接赋值_js 深拷贝 vs 浅拷贝
  2. XML学习笔记01【xml_基础、xml_约束】
  3. 网易2019实习生Java编程题
  4. Spring.NET学习笔记12——面向切面编程(基础篇) Level 300
  5. 动手学PaddlePaddle(2):房价预测
  6. atob和btoa的趣谈
  7. 云计算的概念_云计算概念掀起涨停潮 美利云奠定板块龙头地位
  8. java学习日记之小技巧(跟着变量走一走)
  9. 小米9稳定版系统更新:加入水滴屏形状切换开关
  10. linux查看cpt硬盘命令,Linux基础知识复习之命令篇
  11. matlab绘制不同线性的直方图,在matlab中绘制多个垂直直方图
  12. 中国制盐市场销售动态及需求潜力预测报告(新版)2022-2027年
  13. Hadoop大数据组件简介
  14. 服务器 'XXXXXX' 上的 MSDTC 不可用。解决方法
  15. Drupal7 数据库查询
  16. 【转】经典的劝酒令和挡酒词
  17. 《高效团队待人技巧》的读书笔记
  18. 看完这个,css中position的绝对定位相对定位就懂了
  19. Firefly笔记一之http模块
  20. 鸿蒙股票今日行情,华为鸿蒙的股票

热门文章

  1. ViewPage实现Tab 底部导航 (如微信,微票儿主界面)
  2. 导航上显示某个地点已关闭什么意思_苹果手机中这4个功能最好立马关闭,不然手机耗电特别快...
  3. 算法:主宰这个世界的10大算法
  4. Python学习笔记之威虎山武器库
  5. 深度学习学习率(lr)调参
  6. 如何关闭android bt配对窗口,Android 连接SSID隐藏网络以及 LEAP 认证的方法
  7. 爬虫第五章 selenium模块的应用
  8. python 3.6.6安装fake_Python fake_useragent报错解决方案
  9. IC验证工程师高效战斗手册--高效验证平台搭建和冒烟测试要注意什么?
  10. tplogin手机监控虚拟服务器,tplogincn登录首页手机设置