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