Interview questions java multi-threaded communication (wake up each other, circular printing) wait, notify cases and program stuck problems that may occur due to false wake-up

1. Loop printing

public class OutWord {

    private String word = "输出A";

    public synchronized void outA() throws InterruptedException {
        if (word.equals("B输出")){
            this.wait();
        }

        //输出word
        System.out.println("word = " + word);
        word="B输出";
        this.notify();
    }

    public synchronized void outB() throws InterruptedException {
        if (word.equals("输出A")){
            this.wait();
        }

        //输出word
        System.out.println("word = " + word);
        word="输出A";
        this.notify();
    }

}

public class Test {
    public static void main(String[] args) {
        OutWord outWord = new OutWord();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    outWord.outA();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"线程一").start();

        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                try {
                    outWord.outB();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"线程二").start();
    }
}

​Output result

word = 输出A
word = B输出
word = 输出A
word = B输出
word = 输出A
.........

2. False wakeup

2.1 Code Demonstration

Join us to add two threads. The new threads are print A and print B.

public class Test {
    public static void main(String[] args) {
        OutWord outWord = new OutWord();

        new Thread(()->{
            for (int i = 0; i < 5; i++) {
                try {
                    outWord.outA();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"线程一").start();

        new Thread(()->{
            for (int i = 0; i < 5; i++) {
                try {
                    outWord.outB();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"线程二").start();

        new Thread(()->{
            for (int i = 0; i < 5; i++) {
                try {
                    outWord.outA();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"线程三").start();

        new Thread(()->{
            for (int i = 0; i < 5; i++) {
                try {
                    outWord.outB();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"线程四").start();
    }
}

public class OutWord {

    private String word = "输出A";

    public synchronized void outA() throws InterruptedException {
        if (word.equals("B输出")){
            this.wait();
        }

        //输出word
        System.out.println("word = " + word);
        word="B输出";
        this.notify();
    }

    public synchronized void outB() throws InterruptedException {
        if (word.equals("输出A")){
            this.wait();
        }

        //输出word
        System.out.println("word = " + word);
        word="输出A";
        this.notify();
    }

}

output result

word = 输出A
word = B输出
word = 输出A
word = B输出
word = 输出A
word = B输出
word = 输出A
word = B输出
word = 输出A
word = B输出
word = 输出A
word = B输出
word = B输出
word = B输出
word = B输出
word = B输出

2.2 What is spurious wakeup

It can be seen that the printing order has been messed up, and a false wake-up has occurred: Now there are four threads executing printing tasks. Suppose two of the threads that print B have grabbed the lock successively, but none of them meet the if condition, enter wait() to wait, and release it At this time, the thread that prints A gets the lock, and prints A, and randomly wakes up a thread that prints B. After the thread prints B, it wakes up another thread that prints B. At this time, the printing disorder will occur. The reason: notify wakes up a thread randomly, and the awakened thread will continue to execute the code after wait

2.2.3 Solution

Replace the if condition with while. After the thread is awakened, the condition still needs to be judged. If it is not satisfied, continue to wait to release the lock and wait to be awakened.

public class OutWord {

    private String word = "输出A";

    public synchronized void outA() throws InterruptedException {
      //  System.out.println(Thread.currentThread().getName()+"拿到了锁");
        while (word.equals("B输出")){
          //  System.out.println(Thread.currentThread().getName()+"等待被唤醒");
            this.wait();
       //     System.out.println(Thread.currentThread().getName()+"被唤醒,继续运行");
        }
        //输出word
        System.out.println("word = " + word);
        word="B输出";
        //System.out.println(Thread.currentThread().getName()+"随机唤醒一条线程");
        this.notify();
       // System.out.println(Thread.currentThread().getName()+"执行完毕");
    }

    public synchronized void outB() throws InterruptedException {
       // System.out.println(Thread.currentThread().getName()+"拿到了锁");
        while (word.equals("输出A")){
        //    System.out.println(Thread.currentThread().getName()+"等待被唤醒");
            this.wait();
         //   System.out.println(Thread.currentThread().getName()+"被唤醒,继续运行");
        }

        //输出word
        System.out.println("word = " + word);
        word="输出A";
       // System.out.println(Thread.currentThread().getName()+"随机唤醒一条线程");
        this.notify();
       // System.out.println(Thread.currentThread().getName()+"执行完毕");
    }

}

output result

word = 输出A
word = B输出
word = 输出A
word = B输出
word = 输出A
word = B输出
word = 输出A
word = B输出
word = 输出A
word = B输出
word = 输出A
word = B输出
word = 输出A
word = B输出
word = 输出A
word = B输出
word = 输出A
word = B输出
word = 输出A
word = B输出

The printing sequence has returned to normal, so is there no other problem? We ran it a few times and found that the output table was actually stuck. Is it a deadlock?

image-20220226130432248

3. Solve the problem of program stuck after the false wake-up problem

First of all, we analyze the locks of the same object. Wait will release the lock, and it will also need to re-compete for the lock object after being woken up.

The four conditions of deadlock are not satisfied except for mutual exclusion, so deadlock is impossible

In the code, is it the reason for while that only the while loop is used?

 while(条件){
		this.wait()
}

The next post details the reason for the problem, please leave a message and say your answer

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=324131230&siteId=291194637