虚假唤醒分析

一、虚假唤醒解读

首先我们要明白 if 和 while的区别

先直接看while和if的区别

请添加图片描述

可以看出来,if 是true情况下,if内的代码也只会执行一次

而while直至不满足条件才能跳出while循环

先分析while情况下

public class Demo {
    public static void main(String[] args) {
        Products data = new Products();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data.increment();
            }
        },"A1").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data.decrement();
            }
        },"B1").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data.increment();
            }
        },"A2").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                data.decrement();
            }
        },"B2").start();
    }
}

class Products{
    private int number = 0;

    public synchronized void increment(){
        while (number !=0){
            try {
                System.out.println(Thread.currentThread().getName()+"商品充足,当前商品数量为"+number);
                System.out.println(Thread.currentThread().getName()+"wait前");
                this.wait();
                System.out.println(Thread.currentThread().getName()+"wait后");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        number++;
        System.out.println(Thread.currentThread().getName()+"数据加一 !===>" + number);
        this.notifyAll();
    }

    public synchronized void decrement(){
        while (number == 0){
            try {
                System.out.println(Thread.currentThread().getName()+"商品不足,当前商品数量为"+number);
                System.out.println(Thread.currentThread().getName()+"wait前");
                this.wait();
                System.out.println(Thread.currentThread().getName()+"wait后");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        number--;
        System.out.println(Thread.currentThread().getName()+"数据减一 !===>" + number);
        this.notifyAll();
    }
}

请添加图片描述

可以看出来,当前线程wait后,之后就会唤醒其他线程,获取到CPU的线程 执行wait后面一行代码,可以得出结论 wait后 该线程代码停留在此点,并释放锁,等待唤醒后就会继续执行wait后的代码

由此可以根据if和while的特性推导

​ 如果是while,唤醒后,把wait后面循环体代码执行完后,会判断while是否为true,只有不满足才能跳出while。

​ 如果是if,唤醒后,会直接顺着wait后面的代码执行下去,不会考虑if是否为true

循环体代码执行完后,会判断while是否为true,只有不满足才能跳出while。

​ 如果是if,唤醒后,会直接顺着wait后面的代码执行下去,不会考虑if是否为true

虚假唤醒:当线程从条件变量中苏醒过来时,发现等待的条件并没有满足,该Demo产生的情况是使用if,生产者A1执行完后,唤醒其他线程,获取到的CPU却是生产者A2,A2进入if中后,并没有满足条件,但是由于是if,会顺着执行再次生产一个,消费者同理。

该文章为个人学习过程中的记录,仅供参考

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值