关于生产者消费者的问题
因为 https://blog.51cto.com/u_3631118/3119794 引发的问题
不去掉else
不去掉else影响的是生产者或者消费者的循环次数,如果二者循环次数不一致,就会导致循环慢的那个因为没有收到notify而处于wait状态,从而导致程序无法停止。
去掉else
如果去掉else,消费者每次都能notify生产者,即使生产者处在wait状态,消费者也能通知到,而上一种情况是有可能不会notify生产者,而生产者此时就在wait状态,也就到这了循环次数不一致的问题,如果消费者每次都能notify生产者,那么即使生产者处在wait状态,消费者也能通知到。这就是二者的不同之处:能够保证生产者处于wait状态,也能有消费者notify到。
以下为有问题的实验源代码,把消费者的else去掉就可以解决问题
package com.atguigu.sync;
/**
* @author xiu
* @create 2022-06-04 21:04
*/
public class ThreadDemo1 {
public static void main(String[] args) {
Share share = new Share();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
//生产者慢100毫秒,使问题暴露
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
share.add();
}
}, "add").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
share.decrease();
}
}, "decrease").start();
}
}
class Share {
int num = 0;
int num2;
int count = 0;
//线程交替的三个步骤: 1.判断 2.干活 3.通知
// 判断和通知可以互换顺序,因为已经在锁里边,不会被抢走资源
//生产者方法
public synchronized void add() {
num2++;
if (count == 2) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else
count++;
System.out.println("增加一个剩余" + count);
notifyAll();
System.out.println("生产者次数" + num2);
}
//消费者方法
public synchronized void decrease() {
num++;
if (count == 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
/**
* 带有else的情况
* 去掉else其实就是改变notify的次数,如果notify的次数不够多,生产者总会因为生产满了而卡在wait,导致循环次数变少,而消费者的循环次数不会变少,
* 就是说消费者循环停止之后生产者还没有结束循环,生产者还没有结束循环就会导致生产者生产满了之后达到wait状态,从而整个程序不能结束
*/
/**
* 不带else情况,就是所有情况下都会notify生产者,生产者即使因为生产满了,也会收到notify,此时消费者也会消耗掉,所以生产者不会wait,也就能和消费者配合,最后一起循环结束
*/
} else {
count--;
System.out.println("消耗一个 剩余" + count);
notifyAll();
System.out.println("消费者次数" + num);
}
}
}