文章目录
概述解决办法概述
高并发编程-线程通信_使用wait和notify进行线程间的通信2_多生产者多消费者导致程序假死原因分析 中分析了假死的原因,这里我们来看下改如何解决在多线程下出现的这个问题呢?
解决办法
多线程情况用while而不是if 来判断条件是否满足notify —> notifyAllpackage com.artisan.test;import java.util.stream.Stream;public class MultiProduceConsumerDemo2 {// 对象监视器-锁private final Object LOCK = new Object();// 是否生产出数据的标识private boolean isProduced = false;// volatile 确保可见性, 假设 i 就是生产者生产的数据private volatile int i = 0;public void produce() {synchronized (LOCK) {String msg = isProduced ? "已生产货物" : "没有货物可搬运";// while 每次被唤醒时都会先检查isProduced是否滿足條件再继续// 不能用if的原因:if它将不再判断isProduced是否滿足條件,直接继续,引发错误// 举个例子 t1 ,t2 都进入到了wait ,然后使用if, 唤醒了t2后,不再判断isProduced是否滿足條件// 直接又生产了一个,导致生产多了数据while (isProduced) {try {System.out.println(Thread.currentThread().getName() + " GOT LOCK ,isProduced= " + isProduced + " wait becauseof " + msg);LOCK.wait();} catch (InterruptedException e) {e.printStackTrace();}}i++;System.out.println(Thread.currentThread().getName() + " GOT LOCK ,isProduced= " + isProduced + " Produce:" + i);// 唤醒所有正在等待这个对象的monitor的线程LOCK.notifyAll();isProduced = true;}}public void consume() {// 加锁synchronized (LOCK) {String msg = isProduced ? "已生产货物" : "没有货物可搬运";// while 每次被唤醒时都会先检查isProduced是否滿足條件再继续while (!isProduced) {try {System.out.println(Thread.currentThread().getName() + " wait becauseof " + msg);LOCK.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName() + " GOT LOCK ,isProduced= " + isProduced + " Consume:" + i);//唤醒所有正在等待这个对象的monitor的线程LOCK.notifyAll();isProduced = false;}}public static void main(String[] args) {MultiProduceConsumerDemo2 produceConsumerDemo = new MultiProduceConsumerDemo2();Stream.of("P1", "P2").forEach(n -> new Thread(n) {@Overridepublic void run() {while (true) produceConsumerDemo.produce();}}.start());Stream.of("C1", "C2").forEach(n -> new Thread(n) {@Overridepublic void run() {while (true) produceConsumerDemo.consume();}}.start());}}