您当前的位置: 首页 > 

Dongguo丶

暂无认证

  • 1浏览

    0关注

    472博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

虚假唤醒问题

Dongguo丶 发布时间:2021-09-10 15:21:53 ,浏览量:1

一般而言线程调用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             
关注
打赏
1638062488
查看更多评论
0.1681s