出于好奇,当Java实现wait()和notify()方法时,它们真的只是使用锁吗?即, wait() 获取互斥体,notify() 释放互斥体,notifyAll() 释放所有互斥体(当然在同一个对象中)?
使用wait()和notify()除了比使用锁方便之外还有其他优点吗?
[编辑] 在布莱恩发表评论后,我意识到我自己困惑的是什么:
wait 不加锁,它释放锁并将其传递给正在等待互斥锁的同步语句的其他人,然后等待拥有锁的其他人通知并调用notify,后者将锁传递回原始锁调用 wait 的线程。我想这就是你感到困惑的地方。 – 布莱恩 17 分钟前
其他问题集中在该语言所说的内容上wait
and notify
是 - 但这似乎不是你的问题所在......你谈论的是互斥体,这是一个实现细节,因此是 JVM 特定的。
所以我们需要选择一个 JVM - 让我们选择 openjdk(源可用here http://openjdk.java.net/projects/jdk6/)。 (最终)处理所有这些东西的代码位于hotspot/src/share/vm/runtime/objectMonitor.cpp
.
这维护了两个数据结构 - 等待集和条目集。等待线程被添加到等待集并停放,而尝试获取监视器的线程被添加到条目集然后停放。在notify
从等待集中取出一个线程并将其添加到条目集中。当一个线程释放锁时,它会从条目集中取消驻留一个线程(如果有的话)。请注意,这些集合实际上是作为队列(链接列表)实现的,因此是基于 FIFO 进行处理的。
因此,在这种特殊情况下,实现会以类似的方式对待等待对象的监视器并尝试获取对象的监视器。
但这只是一个 JVM 的一种实现(尽管其他人可能会做类似的事情)——所以我们不能依赖它。所以我想问题是你为什么想知道?如果只是好奇那就看一下openjdk的代码,它很有趣。如果您计划在代码中使用此信息...请不要这样做。
UPDATE
我意识到说“公园”并不能告诉我们太多信息。停放线程的代码是特定于平台的(并且在名为的对象中实现)PlatformEvent
, which ParkEvent
延伸)。在我正在查看的 openjdk 版本中,linux 的 Park 代码可以在以下位置找到hotspot/src/os/linux/vm/os_linux.cpp
这称为pthread_mutex_lock(_mutex)
...所以回答你的问题yes呼叫等待may获取互斥体在我的机器上。请注意,上面发生的很多事情可能会阻止我们到达这一点。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)