一般而言线程调用wait()方法后,需要其他线程调用notify,notifyAll方法后,线程才会从wait方法中返回,
而虚假唤醒(spurious wakeup)是指线程通过判断(如果是if判断),符合条件就进入阻塞,当该线程被其他线程唤醒(在哪里阻塞就在哪里唤醒),就不会判断是否满足if条件,直接程序往下 执行。因为如果不符合if条件判断是不应该执行的,但是该线程却真实的执行了。所以使用if条件判断进入wait阻塞被唤醒后可能出现虚假唤醒问题
synchronized (obj) {
if ()
obj.wait();
... // Perform action appropriate to condition
}
虽然这在实践中很少会发生,但应用程序必须通过测试应该使线程被唤醒的条件来防范,并且如果条件不满足则继续等待。 换句话说,等待应该总是出现在循环中,就像这样:
As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:
synchronized (obj) {
while ()
obj.wait();
... // Perform action appropriate to condition
}
(有关此主题的更多信息,请参阅Doug Lea的“Java并行编程(第二版)”(Addison-Wesley,2000)中的第3.2.3节或Joshua Bloch的“有效Java编程语言指南”(Addison- Wesley,2001)。
案例- 假设这个共享变量的初始值为0,
- 场景—四个线程,如果变量为0,t1、t3可以对变量执行+1操作并唤醒其他线程,如果变量为1进入阻塞
- 如果变量为1,t2、t4可以对变量执行-1操作并唤醒其他线程,如果变量为0进入阻塞
- 每个线程执行10次
package com.dongguo.concurrent.waitnotify;
/**
* @author Dongguo
* @date 2021/9/3 0003-13:15
* @description: 生产者消费者
* 四个线程t1加1,t2减1,t3加1,t4减1
* 虚假唤醒问题
*/
public class ThreadWaitNotifyDemo {
public static void main(String[] args) {
Number number = new Number();
new Thread(() -> {
for (int i = 0; i {
for (int i = 0; i {
for (int i = 0; i {
for (int i = 0; i {
for (int i = 0; i {
for (int i = 0; i {
for (int i = 0; i {
for (int i = 0; i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?