zoukankan      html  css  js  c++  java
  • 【Java多线程】多线程虚假唤醒

    public class CustomerDemo {
        public static void main(String[] args) {
            /**
             * 要求一个线程增加,一个线程减少
             */
            Number number= new Number();
            new Thread(() -> {
                for (int i = 0; i < 10 ;i ++) {
                    try {
                        number.decrease();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "A").start();
    
            new Thread(() -> {
                for (int i = 0; i < 10 ;i ++) {
                    try {
                        number.increase();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "B").start();
    
            new Thread(() -> {
                for (int i = 0; i < 10 ;i ++) {
                    try {
                        number.decrease();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "C").start();
    
    
            new Thread(() -> {
                for (int i = 0; i < 10 ;i ++) {
                    try {
                        number.increase();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "D").start();
        }
    }
    
    
    /**
     * 线程之间的通信
     */
    class Number {
    
        private int num = 0;
    
        public synchronized void decrease() throws InterruptedException {
            if (num == 0) {
                this.wait();
            }
            num --;
            System.out.println(Thread.currentThread().getName() + " ... " + num);
            this.notifyAll();
        }
    
        public synchronized void increase() throws InterruptedException {
            if (num != 0) {
                this.wait();
            }
            num ++;
            System.out.println(Thread.currentThread().getName() + " ... " + num);
            this.notifyAll();
        }
    
    }
    

    上面程序最理想的状态是0 ,1,0,1间隔执行,但是多执行几次就有可能会出现以下情形

    B ... 1
    A ... 0
    B ... 1
    .....
    .....
    A ... -1
    A ... -2
    A ... -3
    A ... -4
    

    这是因为多线程的虚假唤醒导致的,在多线程中判断必须使用while
    如果使用if

     if (num != 0) {
    // 假设此时有B,D线程在这里wait,如果被唤醒后,不会再次进行num != 0判断,这样就会导致num ++ 两次。如果使用while的话,线程被唤醒以后会再次进行条件判断
       this.wait();
     }
    
  • 相关阅读:
    C# 测试 modbusTCP 经验积累
    C#制作透明色GIF动画的类
    C# esc退出窗体
    让PPT演示文稿循环播放
    C# hex 转 float
    C# PowerPoint操作的基本用法。
    将listview的checkbox改成单选。
    google搜索栏设置
    如何在C++中实现Deprecated API Anthony
    只能用new生成的对象 Anthony
  • 原文地址:https://www.cnblogs.com/amberbar/p/13290672.html
Copyright © 2011-2022 走看看