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();
     }
    
  • 相关阅读:
    在luogu上嫖到了一张感觉很NB的图
    luoguP6028算术 题解(推柿子+整除分块+调和级数)
    notebook
    不氵的 0xd
    点分治&&DSU on tree学习笔记
    洛谷10月月赛2T1题解
    概率与期望题库题目整理
    TiDB-TiUP工具使用
    TiDB-单机学习环境部署(4.X版本)
    DB-异构数据库迁移工具
  • 原文地址:https://www.cnblogs.com/amberbar/p/13290672.html
Copyright © 2011-2022 走看看