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

  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(内核级线程),如果要阻塞或唤醒一条线程。则需要操作系统来帮忙完成。这样就不可避免的会陷入用用户态到核心态的转换之中。状态转换是很耗费处理器时间的。虚拟机本身也会进行一些优化,诸如在进入阻塞前,加入一段自旋等待过程。以避免频繁切换。

相关推荐
q***38511 天前
SpringCloud实战十三:Gateway之 Spring Cloud Gateway 动态路由
java·spring cloud·gateway
小白学大数据1 天前
Python爬虫伪装策略:如何模拟浏览器正常访问JSP站点
java·开发语言·爬虫·python
SEO_juper1 天前
别再纠结LLMs.txt了!它背后的真相与最佳使用场景,一文讲透。
开发语言·ai·php·数字营销
程序员西西1 天前
SpringBoot接口安全:APIKey保护指南
java·spring boot·计算机·程序员·编程·编程开发
g***B7381 天前
JavaScript在Node.js中的模块系统
开发语言·javascript·node.js
summer_west_fish1 天前
单体VS微服务:架构选择实战指南
java·微服务·架构
v***8571 天前
Ubuntu介绍、与centos的区别、基于VMware安装Ubuntu Server 22.04、配置远程连接、安装jdk+Tomcat
java·ubuntu·centos
烤麻辣烫1 天前
黑马程序员大事件后端概览(表现效果升级版)
java·开发语言·学习·spring·intellij-idea
q***96581 天前
Spring总结(上)
java·spring·rpc
思密吗喽1 天前
宠物商城系统
java·开发语言·vue·毕业设计·springboot·课程设计·宠物