-
没有参数的wait()方法等价于wait(0),等价于永远等下去。
-
虚假唤醒 :一个线程也能在没有被通知,中断,或超时的情况下被唤醒。也即所谓的"虚假唤醒"。
-
解决虚假唤醒的办法就是通过while循环来判断条件。
-
何为虚假唤醒
-
简单讲,要避免使用 if 的方式来判断条件,否则一旦线程恢复,就继续往下执行,不会再次检测条件。由于可能存在的"虚假唤醒",并不意味着条件是满足的,这点甚至对简单的"二人转"的两个线程的 wait/notify 情况也需要注意。
-
另外,如果对于更多线程的情况,比如"生产者和消费者"问题,一个生产者,两个消费者,更加不能简单用 if 判断。因为可能用的是 notifyAll,两个消费者同时起来,其中一个先抢到了锁,进行了消费,等另一个也抢到锁时,可能条件又不满足了,所以还是要继续判断,不能简单认为被唤醒了就是条件满足了。不过,这是一个不确定的等待,可能等待(无法获取锁时),也可能不等待(能获取锁)。陷入这种阻塞后也没有自主退出的机制。
-
BLOCKED 和 WAITING 状态的区别和联系
-
在说完了 BLOCKED,WAITING 和 TIMED_WAITING 后,我们可以综合来看看它们,比如,阻塞与等待到底有什么本质的区别呢?
-
显然,BLOCKED 同样可以视作是一种特殊的,隐式的 wait/nofity 机制。等待的条件就是"有锁还是没锁"。
-
有一点需要注意的是,BLOCKED 状态是与 Java 语言级别的 synchronized 机制相关的,我们知道在 Java 5.0 之后引入了更多的机制(java.util.concurrent),除了可以用 synchronized 这种内部锁,也可以使用外部的显式锁。
-
显式锁有一些更好的特性,如能中断,能设置获取锁的超时,能够有多个条件等,尽管从表面上说,当显式锁无法获取时,我们还是会说,线程被"阻塞"了,但却未必是 BLOCKED 状态。
-
当锁可用时,其中的一个线程会被系统隐式通知,并被赋予锁,从而获得在同步块中的执行权。
-
显然,等待锁的线程与系统同步机制形成了一个协作关系。
-
对比来看, WAITING 状态属于主动地显式地申请的阻塞,BLOCKED 则属于被动的阻塞,但无论从字面意义还是从根本上来看,并无本质的区别。
-
在前面我们也已经说过,这三个状态可以认为是传统 waiting 状态在 JVM 层面的一个细分。
-
主流java虚拟机的实现中,java线程是映射到操作系统的元素内核线程之上的。Java线程->LWP(轻量级进程)->KLT(内核级线程),如果要阻塞或唤醒一条线程。则需要操作系统来帮忙完成。这样就不可避免的会陷入用用户态到核心态的转换之中。状态转换是很耗费处理器时间的。虚拟机本身也会进行一些优化,诸如在进入阻塞前,加入一段自旋等待过程。以避免频繁切换。
干货-并发编程提高——线程的唤醒(七)
ProMan_XY2024-08-06 15:05
相关推荐
ever_up97337 分钟前
EasyExcel的导入与导出及在实际项目生产场景的一下应用例子吴天德少侠1 小时前
c++返回一个pair类型ok!ko2 小时前
设计模式之工厂模式(通俗易懂--代码辅助理解【Java版】)学地理的小胖砸2 小时前
【GEE的Python API】丷丩3 小时前
一个Java中有用的JacksonUtil类爱摄影的程序猿3 小时前
JAVA springboot面试题今日分享qq_317060953 小时前
java之http client工具类ZJKJTL3 小时前
Spring中使用ResponseStatusExceptionResolver处理HTTP异常响应码robot_大菜鸟3 小时前
python_openCV_计算图片中的区域的黑色比例Pandaconda4 小时前
【C++ 面试 - 新特性】每日 3 题(六)