
Java 并发之虚假唤醒
发布日期:2021-05-07 04:37:41
浏览次数:17
分类:原创文章
本文共 2594 字,大约阅读时间需要 8 分钟。
目录
一、什么是虚假唤醒?
当一个条件满足时,很多线程都被唤醒了,但是只有其中部分是有用的唤醒,其它的唤醒都是无用功1.比如说买货,如果商品本来没有货物,突然进了一件商品,这是所有的线程都被唤醒了 ,但是只能一个人买,所以其他人都是假唤醒,获取不到对象的锁
二、开发中虚假唤醒会造成问题的场景:
例如在多线程的场景中,判断一个线程是否需要阻塞(调用wait())时,如果用 if 判断,就会出问题,因为想想看,多有多个线程都在阻塞时,突然条件满足了(product<1),那么就会有线程唤醒阻塞着的多个线程,但是只有一个线程能拿到锁,其余没拿到锁的线程要是被唤醒了,还继续往下执行,就不对了。
if(product>=1){ wait(); }
所以解决方法是 调用wait的代码块,要用while 来代替 if :
while(product>=1){ wait(); }
三、为什么 if 会产生虚假唤醒
因为if只会执行一次,执行完会接着向下执行if()外边的 而while不会,直到条件满足才会向下执行while()外边的
四、怎么产生虚假唤醒
把 while (product >=1) {} 换成 if (product >=1) {} 就会出现虚假唤醒
下面给个 生产者消费者的代码展示:
public class Test { public static void main(String[] args) { Clerk clerk = new Clerk(); Producer producer = new Producer(clerk); Customer customer = new Customer(clerk); new Thread(producer,"生产者A").start(); new Thread(customer,"消费者A").start(); new Thread(producer,"生产者B").start(); new Thread(customer,"消费者B").start(); }}class Clerk{ private int product=0; public synchronized void add(){ while(product>=1){ System.out.println(Thread.currentThread().getName()+"---还有货物:"+product); try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } product+=1; System.out.println(Thread.currentThread().getName()+" 补货完成,剩余货物:"+product); notifyAll(); } public synchronized void sale(){ while (product<=0){ System.out.println(Thread.currentThread().getName()+" 缺货中:"+product); try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+" 已补货,开始消费..."); product-=1; notifyAll(); }}class Producer implements Runnable{ private Clerk clerk; public Producer(Clerk clerk){ this.clerk = clerk; } @Override public void run() { for (int i=0;i<20;i++){ try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } clerk.add(); } }}class Customer implements Runnable{ private Clerk clerk; public Customer(Clerk clerk){ this.clerk = clerk; } @Override public void run() { for (int i = 0; i < 20; i++) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } clerk.sale(); } }}
发表评论
最新留言
感谢大佬
[***.8.128.20]2025年04月01日 11时45分19秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Flower
2021-05-08
Nginx---惊群
2021-05-08
供应ASTM D3475认证丨ASTM D3475防儿童包装测试费用
2021-05-08
2种解法 - 获取一条直线上最多的点数
2021-05-08
项目中常用的审计类型概述
2021-05-08
新生儿不建议吃鱼肝油,这些你知道吗
2021-05-08
新生儿哭是因为什么
2021-05-08
nodeName与tagName的区别
2021-05-08
(九)实现页面底部购物车的样式
2021-05-08
在vue中给对象扩展属性的方法
2021-05-08
Neo4j : 通过节点的 id属性 对节点进行查,改,删操作
2021-05-08
Linux标准错误和标准输出重定向到同一个文件
2021-05-08
【2021年新书推荐】ASP.NET Core 5 and Angular
2021-05-08
python-day3 for语句完整使用
2021-05-08
java基础知识:构造函数
2021-05-08
java基础知识:封装
2021-05-08