The problem of false awakening between producers and consumers

What is a false wakeup?

When a condition is met, multiple threads are awakened, and some of them cannot be executed but perform
operations such as operating a variable: number is initially 0, thread A +1 to number, and thread B is -1 to number. There is no problem now . However, when thread C performs +1 on number and thread D performs -1 on number, there will be more than 0 and 1 results.

Why is there a negative number when the lock is clearly added?

It is because wait is placed in the if judgment.
The if judgment is executed only once, and then the following if() is executed. While while will always judge, the code below while() will be executed until the conditions are met

Code reason:

if (number != 0){
    this.wait();//等待
}

The solution is to replace if in two places with while.

while (number != 0){
    this.wait();//等待
}

Below is the code that does not generate false wakeups. (Replace while with if to cause false wakeup)

/**
 * 虚假唤醒
 * 线程交替执行  操作同一个变量 num
 */
public class A {
    
    
    public static void main(String[] args) {
    
    
        Data data = new Data();

        new Thread(()->{
    
    
            for (int i = 0; i < 5; i++) {
    
    
                try {
    
    
                    data.increment();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        },"A").start();

        new Thread(()->{
    
    
            for (int i = 0; i < 5; i++) {
    
    
                try {
    
    
                    data.decrement();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        },"BB").start();

        new Thread(()->{
    
    
            for (int i = 0; i < 5; i++) {
    
    
                try {
    
    
                    data.increment();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        },"CCC").start();

        new Thread(()->{
    
    
            for (int i = 0; i < 5; i++) {
    
    
                try {
    
    
                    data.decrement();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        },"DDDD").start();
    }
}

//数字 资源类
class Data{
    
    
    private int number = 0;

    //执行 +1
    public synchronized void increment() throws InterruptedException {
    
    
        while (number != 0){
    
    
            this.wait();//等待
        }
        number++;
        System.out.println(Thread.currentThread().getName()+"->"+number);
        //通知其他线程,+1完毕
        this.notifyAll();
    }

    //执行 -1
    public synchronized void decrement() throws InterruptedException {
    
    
        while (number==0){
    
    
            this.wait();//等待
        }
        number--;
        System.out.println(Thread.currentThread().getName()+"->"+number);
        //通知其他线程,-1完毕
        this.notifyAll();
    }
}

Guess you like

Origin blog.csdn.net/qq_42524288/article/details/106001951