一、虚假唤醒解读
首先我们要明白 if 和 while的区别
先直接看while和if的区别
可以看出来,if 是true情况下,if内的代码也只会执行一次
而while直至不满足条件才能跳出while循环
先分析while情况下
public class Demo {
public static void main(String[] args) {
Products data = new Products();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
data.increment();
}
},"A1").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
data.decrement();
}
},"B1").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
data.increment();
}
},"A2").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
data.decrement();
}
},"B2").start();
}
}
class Products{
private int number = 0;
public synchronized void increment(){
while (number !=0){
try {
System.out.println(Thread.currentThread().getName()+"商品充足,当前商品数量为"+number);
System.out.println(Thread.currentThread().getName()+"wait前");
this.wait();
System.out.println(Thread.currentThread().getName()+"wait后");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
number++;
System.out.println(Thread.currentThread().getName()+"数据加一 !===>" + number);
this.notifyAll();
}
public synchronized void decrement(){
while (number == 0){
try {
System.out.println(Thread.currentThread().getName()+"商品不足,当前商品数量为"+number);
System.out.println(Thread.currentThread().getName()+"wait前");
this.wait();
System.out.println(Thread.currentThread().getName()+"wait后");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
number--;
System.out.println(Thread.currentThread().getName()+"数据减一 !===>" + number);
this.notifyAll();
}
}
可以看出来,当前线程wait后,之后就会唤醒其他线程,获取到CPU的线程 执行wait后面一行代码,可以得出结论 wait后 该线程代码停留在此点,并释放锁,等待唤醒后就会继续执行wait后的代码
由此可以根据if和while的特性推导
如果是while,唤醒后,把wait后面循环体代码执行完后,会判断while是否为true,只有不满足才能跳出while。
如果是if,唤醒后,会直接顺着wait后面的代码执行下去,不会考虑if是否为true
循环体代码执行完后,会判断while是否为true,只有不满足才能跳出while。
如果是if,唤醒后,会直接顺着wait后面的代码执行下去,不会考虑if是否为true
虚假唤醒:当线程从条件变量中苏醒过来时,发现等待的条件并没有满足,该Demo产生的情况是使用if,生产者A1执行完后,唤醒其他线程,获取到的CPU却是生产者A2,A2进入if中后,并没有满足条件,但是由于是if,会顺着执行再次生产一个,消费者同理。
该文章为个人学习过程中的记录,仅供参考