# 第二节 虚假唤醒

# 1、提出问题

把上面代码中的两个线程扩展到四个线程:

        // 创建两个线程
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                demo.incr();
            }
        }, "[线程A]").start();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                demo.decr();
            }
        }, "[线程B]").start();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                demo.incr();
            }
        }, "[线程C]").start();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                demo.decr();
            }
        }, "[线程D]").start();

打印效果如下:

# ……

[线程B]num=0
[线程C]num=1
[线程A]num=2
[线程A]num=3
[线程A]num=4
[线程A]num=5
[线程A]num=6
[线程A]num=7
[线程A]num=8
[线程A]num=9
[线程C]num=10
[线程C]num=11

……

# 2、分析问题

images

images

# 3、解决问题

解决线程虚假唤醒的问题,关键在于把 if 判断改成while判断:

images

# 4、小结

虚假唤醒情况的关键点:

  • 关键点1:线程是经过了一次判断后,进入到代码块中才被wait()进入等待状态
  • 关键点2:线程在等待期间,判断条件其实已经不满足了
  • 关键点3:if 判断的正常的下一步不是再次判断,而是继续执行代码块后面的代码
  • 关键点4:while判断的正常的下一步是再次判断,从而杜绝了『条件不满足但还是执行操作』的情况

上一节 回目录 下一节