java multithreaded communication (mutual wake-up, circular printing) wait,notify cases and possible program blocking problems of false wake-up

Posted by rockofaith on Sat, 26 Feb 2022 06:20:49 +0100

1. Circular printing

public class OutWord {

    private String word = "output A";

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

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

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

        //Output word
        System.out.println("word = " + word);
        word="output 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();
                }
            }
        },"Thread one").start();

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

Output results

word = output A
word = B output
word = output A
word = B output
word = output A
.........

2. False Awakening

2.1 code demonstration

Join us and add two new threads: 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();
                }
            }
        },"Thread one").start();

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

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

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

public class OutWord {

    private String word = "output A";

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

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

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

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

}

Output results

word = output A
word = B output
word = output A
word = B output
word = output A
word = B output
word = output A
word = B output
word = output A
word = B output
word = output A
word = B output
word = B output
word = B output
word = B output
word = B output

2.2 what is false awakening

It can be seen that the printing sequence has been disordered and there is A false wake-up: now there are four threads executing the printing task. Suppose that two threads of print B successively grab the lock, but they do not meet the if condition, enter the wait() and release the lock. At this time, the thread of print A gets the lock, prints A and wakes up A thread of print B at random, The thread wakes up another thread of printing B after printing B. at this time, the printing order will be out of order. Reason: notify wakes up A thread randomly, and the awakened thread will continue to execute the code after the wait

2.2.3 solutions

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

public class OutWord {

    private String word = "output A";

    public synchronized void outA() throws InterruptedException {
      //  System.out.println(Thread.currentThread().getName() + "got the lock");
        while (word.equals("B output")){
          //  System.out.println(Thread.currentThread().getName() + "waiting to be awakened");
            this.wait();
       //     System.out.println(Thread.currentThread().getName() + "wake up and continue running");
        }
        //Output word
        System.out.println("word = " + word);
        word="B output";
        //System.out.println(Thread.currentThread().getName() + "wake up a thread randomly");
        this.notify();
       // System.out.println(Thread.currentThread().getName() + "execution completed");
    }

    public synchronized void outB() throws InterruptedException {
       // System.out.println(Thread.currentThread().getName() + "got the lock");
        while (word.equals("output A")){
        //    System.out.println(Thread.currentThread().getName() + "waiting to be awakened");
            this.wait();
         //   System.out.println(Thread.currentThread().getName() + "wake up and continue running");
        }

        //Output word
        System.out.println("word = " + word);
        word="output A";
       // System.out.println(Thread.currentThread().getName() + "wake up a thread randomly");
        this.notify();
       // System.out.println(Thread.currentThread().getName() + "execution completed");
    }

}

Output results

word = output A
word = B output
word = output A
word = B output
word = output A
word = B output
word = output A
word = B output
word = output A
word = B output
word = output A
word = B output
word = output A
word = B output
word = output A
word = B output
word = output A
word = B output
word = output A
word = B output

The printing sequence has returned to normal. Is there no other problem? We run it several times and find that the output table is stuck. Is it a deadlock

3. The program is stuck after solving the false wake-up problem

First of all, we analyze that the lock is the same object. wait will release the lock. After being awakened, we also need to re compete for the lock object

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

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

 while(condition){
		this.wait()
}

The next post details the reason for the problem. Welcome to leave a message and say your answer

Topics: Java Back-end Interview Multithreading