1 回答
![?](http://img1.sycdn.imooc.com/54584c9c0001489602200220-100-100.jpg)
TA贡献1796条经验 获得超4个赞
规格notify()
说:
如果有任何线程在此对象上等待,则选择其中一个唤醒。该选择是任意的,并且可以根据实现情况进行选择。
这意味着您不能期望任何特定的顺序,而实现可能会使用它想要的任何特定的顺序,包括调用的顺序wait
。
没有理由为什么实现应该实现改组。那只会浪费资源。使实现具有自由的原因是允许他们在适合时使用更高效的算法,而不必维护命令。
因此,由于存储结构不同,不同的实现可能会以相反的顺序唤醒它们。如果实现切换到阈值以上的其他存储结构,则它也可能随着一定数量的排队线程而改变。
除此之外,您的测试代码非常特别。您的主线程在调用之前会等待很长时间notify()
,因此所有线程可能已经进入等待状态,并存储在JVM使用的任何数据结构中。然后,一次只有一个挂起notify()
,因为让唤醒的线程进行下一个挂起notify()
。如果您允许操作重叠,则图片可能会发生巨大变化。
然后,可能会发现底层数据结构不是纯FIFO。同样,对于实现来说,wait()
如果有待处理的线程允许线程调用立即继续进行notify()
,而不考虑等待队列,而绕过所有已排队的线程,这是一种安静的做法,因为这样做效率更高。
另一点是,如果有多个挂起notify()
,则唤醒的线程必须竞争重新获取对象监视器。这取决于操作系统的调度程序和实际的系统负载,哪个线程将在此处成功执行,因此,即使按入队的顺序唤醒了这些线程,由于JVM无法控制的详细信息,线程仍可能在此位置被超越。
另外,请不要忘记规范允许虚假唤醒。因此,一个不能够单独唤醒单个线程的JVM可以在notify()
不违反规范的情况下,由于一次调用而唤醒多个线程。
添加回答
举报