题目:现在两个线程,可以操作初始值为零的一个变量实现一个线程对该变量加一,一个线程对该变量减一实现交替,来10轮,变量初始值为0
代码演示:
package juc; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 题目:现在两个线程,可以操作初始值为零的一个变量 * 实现一个线程对该变量加一,一个线程对该变量减一 * 实现交替,来10轮,变量初始值为0 */ public class ThreadWaitNotifyDemo { public static void main(String[] args) { AirConditioner airConditioner = new AirConditioner(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { airConditioner.increase(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "A").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { airConditioner.decrease(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "B").start(); } } // 资源类 class AirConditioner { private int num = 0; Lock lock = new ReentrantLock(); public synchronized void increase() throws InterruptedException { // 1.判断 if(num != 0){ this.wait(); } // 2.干活 System.out.println(num+"被"+Thread.currentThread().getName()+"进行加一后为:"+ ++num); // 3.通知 this.notify(); } public synchronized void decrease() throws InterruptedException { // 1.判断 if(num == 0){ this.wait(); } // 2.干活 System.out.println(num+"被"+Thread.currentThread().getName()+"进行减一后为:"+ --num); // 3.通知 this.notify(); } }
运行结果:
当我们再加两个线程,也就是两个线程执行加法,两个线程执行减法。
package juc; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 题目:现在两个线程,可以操作初始值为零的一个变量 * 实现一个线程对该变量加一,一个线程对该变量减一 * 实现交替,来10轮,变量初始值为0 * <p> * 1.在高内聚低耦合的前提下, 线程 操作(对外暴露的调用方法) 资源类 * 2.判断/干活/通知 */ public class ThreadWaitNotifyDemo { public static void main(String[] args) { AirConditioner airConditioner = new AirConditioner(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { airConditioner.increase(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "A").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { airConditioner.increase(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "B").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { airConditioner.decrease(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "C").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { airConditioner.decrease(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "D").start(); } } // 资源类 class AirConditioner { private int num = 0; Lock lock = new ReentrantLock(); public synchronized void increase() throws InterruptedException { // 1.判断 if (num != 0) { this.wait(); } // 2.干活 System.out.println(num + "被" + Thread.currentThread().getName() + "进行加一后为:" + ++num); // 3.通知 this.notify(); } public synchronized void decrease() throws InterruptedException { // 1.判断 if (num == 0) { this.wait(); } // 2.干活 System.out.println(num + "被" + Thread.currentThread().getName() + "进行减一后为:" + --num); // 3.通知 this.notify(); } }
结果:
这时我们发现,结果和我们想象的不太一样,原因是由于多线程的虚假唤醒。
解决方法:判断用while不用if。
代码演示:
package juc; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 题目:现在两个线程,可以操作初始值为零的一个变量 * 实现一个线程对该变量加一,一个线程对该变量减一 * 实现交替,来10轮,变量初始值为0 * <p> * 1.在高内聚低耦合的前提下, 线程 操作(对外暴露的调用方法) 资源类 * 2.判断/干活/通知 * 3.多线程交互中,必须防止多线的虚假唤醒 (也即判断只能用while,不能用if) */ public class ThreadWaitNotifyDemo { public static void main(String[] args) { AirConditioner airConditioner = new AirConditioner(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { airConditioner.increase(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "A").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { airConditioner.increase(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "B").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { airConditioner.decrease(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "C").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { try { airConditioner.decrease(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "D").start(); } } // 资源类 class AirConditioner { private int num = 0; Lock lock = new ReentrantLock(); public synchronized void increase() throws InterruptedException { // 1.判断 while (num != 0) { this.wait(); } // 2.干活 System.out.println(num + "被" + Thread.currentThread().getName() + "进行加一后为:" + ++num); // 3.通知 this.notify(); } public synchronized void decrease() throws InterruptedException { // 1.判断 while (num == 0) { this.wait(); } // 2.干活 System.out.println(num + "被" + Thread.currentThread().getName() + "进行减一后为:" + --num); // 3.通知 this.notify(); } }
结果:
原文:https://www.cnblogs.com/lililixuefei/p/13185918.html