《狂神说-JUC》【2】 刨根问底系列(1)——虚假唤醒(spurious wakeups)的原因以及在pthread_cond_wait、pthread_cond_singal中使用while的必要性

https://gitee.com/kuangstudy/openclass/tree/master/%E7%8B%82%E7%A5%9E%E8%AF%B4JUC%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B

 

 

   
   

 

如果改成 ABCD 4个线程,就会出问题了

 虚假唤醒问题

i解决方案:if -> while   

要理解问题所在,需要了解以下知识

  1. 线程获取不到锁被阻塞,会在Contention List上等待
  2. 获取到锁的线程调用wait后,会主动放弃锁,并在Wait Set中等待唤醒
  3. 线程调用notify后,在退出Synchronized块释放锁后才会执行唤醒操作(暂时没有搞清楚唤醒和释放锁的顺序)

具体请参考Java锁Synchronized之阻塞线程

上面问题的核心是: C1被唤醒后,仍然需要先获取锁再继续执行逻辑,而唤醒-获取锁并不是原子性的,唤醒之后锁可能被其他线程获取,这时C1再次获取到锁时,产品已经没了,由于是继续执行,就没有再检查产品数量,导致异常情况的出现

解决办法—将if替换为while

替换为while后,即使被唤醒,仍然会再检查一遍限制条件,保证逻辑的正确性.


作者:alonwang
链接:https://juejin.im/post/5d32a6545188257f3850d514
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 
   

 

 https://www.cnblogs.com/whuwzp/p/paogenwendi_spurious_wakeups.html

刨根问底系列(1)——虚假唤醒(spurious wakeups)的原因以及在pthread_cond_wait、pthread_cond_singal中使用while的必要性

 

 

 

 

 

 

 

去掉重复代码提示波浪线

4个线程的结果也对了

问题:现在是【随机】执行,如何【有序】执行 —— Condition 的优势就体现出来了(精准地通知和唤醒线程);

 

精准唤醒

 测试

结果符合要求

 应用场景:

 

 

 

 

 

 

 hello 先执行,延迟4秒后再发短信

普通方法不是同步方法,不受锁的影响

 结果:先打电话 再发短信

因为是两把锁...

 结果是先发短信再打电话

 

 

  

 结果是一样的

猜你喜欢

转载自www.cnblogs.com/cx2016/p/13172439.html