线程间通信 生产者消费者虚假唤醒
Posted hpdblogs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程间通信 生产者消费者虚假唤醒相关的知识,希望对你有一定的参考价值。
线程通信中要预防虚假唤醒 注意(在哪里停就在哪里启动)
class shareDataOne{
private int number = 0;
public synchronized void incr() throws InterruptedException {
if(number != 0){
this.wait();//等待 不可以用if 必须用while进行判断
}
number++;
System.out.println(Thread.currentThread().getName()+" "+number);
this.notifyAll();//唤醒
}
public synchronized void decr() throws InterruptedException {
if(number == 0){
this.wait();//等待 不可以用if 必须用while进行判断
}
number--;
System.out.println(Thread.currentThread().getName()+" "+number);
this.notifyAll();
}
}
结果
DD 0
AA 1
CC 2
DD 1
DD 0
CC 1
class shareDataOne{
private int number = 0;
public synchronized void incr() throws InterruptedException {
while(number != 0){ //正确的写法
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+" "+number);
this.notifyAll();
}
public synchronized void decr() throws InterruptedException {
while(number == 0){
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName()+" "+number);
this.notifyAll();
}
}
结果:
DD 0
CC 1
DD 0
AA 1
DD 0
CC 1
使用Lock实现
public class Test02 { public static void main(String[] args) { shareDataOne shareDataOne = new shareDataOne(); new Thread(() -> { for (int i = 0; i <= 10; i++) { shareDataOne.incr(); } }, "AA").start(); new Thread(() -> { for (int i = 0; i <= 10; i++) { shareDataOne.decr(); } }, "BB").start(); new Thread(() -> { for (int i = 0; i <= 10; i++) { shareDataOne.incr(); } }, "CC").start(); new Thread(() -> { for (int i = 0; i <= 10; i++) { shareDataOne.decr(); } }, "DD").start(); } } class shareDataOne { private int number = 0; private Lock lock = new ReentrantLock(); private Condition cd = lock.newCondition(); public void incr() { lock.lock(); try { while (number != 0) { cd.await(); } number++; System.out.println(Thread.currentThread().getName() + " " + number); cd.signalAll();//此处唤醒用ALL避免死锁 } catch (Exception e) { } finally { lock.unlock(); } } public void decr() { lock.lock(); try { while (number == 0) { cd.await(); } number--; System.out.println(Thread.currentThread().getName() + " " + number); cd.signalAll();//此处唤醒用ALL避免死锁 } catch (Exception e) { } finally { lock.unlock(); } } }
以上是关于线程间通信 生产者消费者虚假唤醒的主要内容,如果未能解决你的问题,请参考以下文章
Java-JUC:使用wait,notify|notifyAll完成生产者消费者通信,虚假唤醒(Spurious Wakeups)问题出现场景,及问题解决方案。