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();
     }
    
  • 相关阅读:
    ansj分词原理
    于erlang依赖的linux调优
    Gearman
    生成具有三态背景图片的按钮
    tracert
    Wings 3D
    jira
    Erlang编程语言的一些痛点
    QTreeView 限制特定的深度、特定深度下的列 是否可以编辑
    QStandardItemModel角色控制及QTreeView添加不同的右键菜单
  • 原文地址:https://www.cnblogs.com/amberbar/p/13290672.html
Copyright © 2011-2022 走看看