传统的生产者消费者问题,防止虚假唤醒
传统的生产者消费者问题,防止虚假唤醒
注意点:wait需要被放进while代码块中,防止虚假唤醒
存在虚假唤醒代码:
package com.example.juc;
public class TestPc {
public static void main(String[] args) {
A a = new A();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
a.increase();
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
a.decrease();
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
a.increase();
}
}, "C").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
a.decrease();
}
}, "D").start();
}
}
class A {
private int num;
public synchronized void increase() {
// 等待
if (num != 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//
System.out.println(Thread.currentThread().getName() + "-->" + ++num);
notifyAll();
}
public synchronized void decrease() {
// 等待
if (num == 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//
System.out.println(Thread.currentThread().getName() + "-->" + --num);
notifyAll();
}
}
多运行几次可能会出现以下异常结果
A-->1
B-->0
A-->1
B-->0
A-->1
B-->0
A-->1
B-->0
C-->1
A-->2
C-->3
A-->4
C-->5
A-->6
C-->7
A-->8
C-->9
A-->10
C-->11
A-->12
C-->13
D-->12
D-->11
D-->10
D-->9
D-->8
D-->7
D-->6
D-->5
D-->4
D-->3
B-->2
B-->1
B-->0
C-->1
B-->0
C-->1
B-->0
C-->1
B-->0
不存在虚假唤醒代码:将if 改为while即可
package com.example.juc;
public class TestPc {
public static void main(String[] args) {
A a = new A();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
a.increase();
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
a.decrease();
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
a.increase();
}
}, "C").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
a.decrease();
}
}, "D").start();
}
}
class A {
private int num;
public synchronized void increase() {
// 等待
while (num != 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//
System.out.println(Thread.currentThread().getName() + "-->" + ++num);
notifyAll();
}
public synchronized void decrease() {
// 等待
while (num == 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//
System.out.println(Thread.currentThread().getName() + "-->" + --num);
notifyAll();
}
}
A-->1
B-->0
A-->1
B-->0
A-->1
B-->0
A-->1
B-->0
A-->1
B-->0
A-->1
B-->0
A-->1
B-->0
A-->1
B-->0
A-->1
B-->0
A-->1
B-->0
C-->1
D-->0
C-->1
D-->0
C-->1
D-->0
C-->1
D-->0
C-->1
D-->0
C-->1
D-->0
C-->1
D-->0
C-->1
D-->0
C-->1
D-->0
C-->1
D-->0