干货-并发编程提高——线程的唤醒(七)

  1. 没有参数的wait()方法等价于wait(0),等价于永远等下去。

  2. 虚假唤醒 :一个线程也能在没有被通知,中断,或超时的情况下被唤醒。也即所谓的"虚假唤醒"。

  3. 解决虚假唤醒的办法就是通过while循环来判断条件。

  4. 何为虚假唤醒

  5. 简单讲,要避免使用 if 的方式来判断条件,否则一旦线程恢复,就继续往下执行,不会再次检测条件。由于可能存在的"虚假唤醒",并不意味着条件是满足的,这点甚至对简单的"二人转"的两个线程的 wait/notify 情况也需要注意。

  6. 另外,如果对于更多线程的情况,比如"生产者和消费者"问题,一个生产者,两个消费者,更加不能简单用 if 判断。因为可能用的是 notifyAll,两个消费者同时起来,其中一个先抢到了锁,进行了消费,等另一个也抢到锁时,可能条件又不满足了,所以还是要继续判断,不能简单认为被唤醒了就是条件满足了。不过,这是一个不确定的等待,可能等待(无法获取锁时),也可能不等待(能获取锁)。陷入这种阻塞后也没有自主退出的机制。

  7. BLOCKED 和 WAITING 状态的区别和联系

  8. 在说完了 BLOCKED,WAITING 和 TIMED_WAITING 后,我们可以综合来看看它们,比如,阻塞与等待到底有什么本质的区别呢?

  9. 显然,BLOCKED 同样可以视作是一种特殊的,隐式的 wait/nofity 机制。等待的条件就是"有锁还是没锁"。

  10. 有一点需要注意的是,BLOCKED 状态是与 Java 语言级别的 synchronized 机制相关的,我们知道在 Java 5.0 之后引入了更多的机制(java.util.concurrent),除了可以用 synchronized 这种内部锁,也可以使用外部的显式锁。

  11. 显式锁有一些更好的特性,如能中断,能设置获取锁的超时,能够有多个条件等,尽管从表面上说,当显式锁无法获取时,我们还是会说,线程被"阻塞"了,但却未必是 BLOCKED 状态。

  12. 当锁可用时,其中的一个线程会被系统隐式通知,并被赋予锁,从而获得在同步块中的执行权。

  13. 显然,等待锁的线程与系统同步机制形成了一个协作关系。

  14. 对比来看, WAITING 状态属于主动地显式地申请的阻塞,BLOCKED 则属于被动的阻塞,但无论从字面意义还是从根本上来看,并无本质的区别。

  15. 在前面我们也已经说过,这三个状态可以认为是传统 waiting 状态在 JVM 层面的一个细分。

  16. 主流java虚拟机的实现中,java线程是映射到操作系统的元素内核线程之上的。Java线程->LWP(轻量级进程)->KLT(内核级线程),如果要阻塞或唤醒一条线程。则需要操作系统来帮忙完成。这样就不可避免的会陷入用用户态到核心态的转换之中。状态转换是很耗费处理器时间的。虚拟机本身也会进行一些优化,诸如在进入阻塞前,加入一段自旋等待过程。以避免频繁切换。

相关推荐
ever_up97337 分钟前
EasyExcel的导入与导出及在实际项目生产场景的一下应用例子
java·开发语言·数据库
吴天德少侠1 小时前
c++返回一个pair类型
开发语言·c++
ok!ko2 小时前
设计模式之工厂模式(通俗易懂--代码辅助理解【Java版】)
java·开发语言·设计模式
学地理的小胖砸2 小时前
【GEE的Python API】
大数据·开发语言·前端·python·遥感·地图学·地理信息科学
丷丩3 小时前
一个Java中有用的JacksonUtil类
java·json·工具
爱摄影的程序猿3 小时前
JAVA springboot面试题今日分享
java·spring boot·spring·面试
qq_317060953 小时前
java之http client工具类
java·开发语言·http
ZJKJTL3 小时前
Spring中使用ResponseStatusExceptionResolver处理HTTP异常响应码
java·spring·http
robot_大菜鸟3 小时前
python_openCV_计算图片中的区域的黑色比例
开发语言·python·opencv
Pandaconda4 小时前
【C++ 面试 - 新特性】每日 3 题(六)
开发语言·c++·经验分享·笔记·后端·面试·职场和发展