Java多线程虚假唤醒问题(生产者和消费者关系)
Posted Go After
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程虚假唤醒问题(生产者和消费者关系)相关的知识,希望对你有一定的参考价值。
何为虚假唤醒:
当一个条件满足时,很多线程都被唤醒了,但是只有其中部分是有用的唤醒,其它的唤醒都是无用功;
比如买货:如果商品本来没有货物,突然进了一件商品,这是所有的线程都被唤醒了,但是只能一个人买,所以其他人都是假唤醒,获取不到对象的锁;
避免虚假唤醒:
避免虚假唤醒的示例:这里使用了 Lambda 表达式
package com.jia.pc; public class A { public static void main(String[] args) { Data data = new Data(); new Thread(()->{ for (int i = 0; i < 10 ; i++) { try { data.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"A").start(); new Thread(()->{ for (int i = 0; i < 10 ; i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"B").start(); new Thread(()->{ for (int i = 0; i < 10 ; i++) { try { data.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } },"C").start(); new Thread(()->{ for (int i = 0; i < 10 ; i++) { try { data.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } },"D").start(); } } // 等待,业务,通知 class Data{ private int number = 0; // +1 public synchronized void increment() throws InterruptedException { while (number != 0){ // 等待 this.wait(); } number++; System.out.println(Thread.currentThread().getName() + "->" + number); // 通知其他线程,我+1完毕 this.notifyAll(); } // -1 public synchronized void decrement() throws InterruptedException { while (number == 0){ // 等待 this.wait(); } number--; System.out.println(Thread.currentThread().getName() + "->" + number); // 通知其他线程,我-1完毕 this.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 Process finished with exit code 0
虚假幻想是如何产生的?
把 while (number != 0) {}
换成 if (number == 0) {}
就会出现虚假唤醒
为什么if判断会出现虚假唤醒?
1. 因为if只会执行一次,执行完会接着向下执行if()外边的
2. 而while不会,直到条件满足才会向下执行while()外边的
以上是关于Java多线程虚假唤醒问题(生产者和消费者关系)的主要内容,如果未能解决你的问题,请参考以下文章