0
点赞
收藏
分享

微信扫一扫

多线程之间的交互编程(虚假唤醒)


结论:

1、高聚低合前提下,线程操作资源类

2、判断/干活/通知

3、多线程交互中,必须要防止多线程的虚假唤醒,也即(判断只用while,不能用if)

4、标记位

 

题目:

一个空调,两个人,一人关,一人开,交替进行。 

package main.test;

/**
* @Auther: wdq
* @Date: 2020/4/19 15:53
* @Description:
*/
class AirConditioner {
private int number = 0;
public synchronized void increament() throws InterruptedException {
//wait
if(number==1){
this.wait();
}
//work
number++;
System.out.println(Thread.currentThread().getName()+"\t"+number);
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
//wait
if(number==0){
this.wait();
}
//work
number--;
System.out.println(Thread.currentThread().getName()+"\t"+number);
this.notifyAll();
}
}
public class threadWaitNotify {
public static void main(String[] args) {
AirConditioner airConditioner = new AirConditioner();

new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
airConditioner.increament();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"A").start();

new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
airConditioner.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"B").start();
}
}

 输出的结果为:

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

看起来结果很正确,但是如果新增两个人,变成四个人对空调开关,两人开,两人关,交替进行。 

package main.test;

/**
* @Auther: wdq
* @Date: 2020/4/19 15:53
* @Description:
*/
class AirConditioner {
private int number = 0;
public synchronized void increament() throws InterruptedException {
//wait
if(number==1){
this.wait();
}
//work
number++;
System.out.println(Thread.currentThread().getName()+"\t"+number);
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
//wait
if(number==0){
this.wait();
}
//work
number--;
System.out.println(Thread.currentThread().getName()+"\t"+number);
this.notifyAll();
}
}
public class threadWaitNotify {
public static void main(String[] args) {
AirConditioner airConditioner = new AirConditioner();

new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
airConditioner.increament();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"A").start();

new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
airConditioner.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"B").start();

new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
airConditioner.increament();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"C").start();

new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
airConditioner.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"D").start();
}
}

部分结果为:

A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
C 1
A 2
A 3
A 4
A 5
A 6
A 7
A 8
A 9
A 10
A 11
A 12
A 13
A 14
C 15

你会发现操作出错了。

这就是wait的虚假唤醒。

官网上的解释:

多线程之间的交互编程(虚假唤醒)_ide

所有不能用if区判断而执行wait方法,要用while。

把上面的if改成while就行了。

举报

相关推荐

0 条评论