Java wait(),notify()的实现是否与锁明显不同?

Ven*_*tta 8 java concurrency multithreading locking wait

出于好奇,当Java实现wait()和notify()方法时,它们真的只是使用锁吗?即,wait()获取互斥锁,notify()释放互斥锁,notifyAll()释放所有互斥锁(当然在同一个对象中)?

除了比使用锁更简单之外,使用wait()和notify()还有其他优点吗?

[编辑]我意识到在Brian的评论之后我对此感到困惑:

等待没有锁定,它释放锁定并将其传递给正在等待互斥锁的同步语句的其他人,然后等待有锁定并通知的其他人通知,这会将锁定传回原始状态调用等待的线程.我认为这就是你感到困惑的地方. - 布赖恩17分钟前

sel*_*lig 13

其他的问题都集中在什么语言说,waitnotify是-但似乎并没有被你的问题是什么?你说说互斥体,这是一个实现细节,因此JVM具体.

所以我们需要选择一个JVM - 让我们选择openjdk(这里有源代码).(最终)处理所有这些东西的代码位于hotspot/src/share/vm/runtime/objectMonitor.cpp.

这维护了两个数据结构 - 等待集和条目集.等待线程被添加到等待集并停放,而尝试接收监视器的线程被添加到条目集然后停止.在notify线程从等待集中获取并添加到条目集.当一个线程释放锁时,如果有一个线程,它会从一个线程中取消一个线程.请注意,这些集实际上是作为队列(链表)实现的,因此基于FIFO进行处理.

因此,在这种特定情况下,实现处理等待对象的监视器并尝试以类似的方式获取对象的监视器.

但这只是一个JVM的一个实现(尽管其他人可能会做类似的事情) - 所以我们不能依赖它.所以我想问题是你为什么想知道?如果仅仅是好奇心,那么请查看openjdk代码,这很有趣.如果您打算在代码中使用此信息,请不要这样做.

UPDATE

我意识到说"公园"并没有告诉我们多少.的代码,公园线程是平台特定的(和在称为对象被实现PlatformEvent,其ParkEvent延伸).在OpenJDK的版本,我正在看的Linux园区代码可以在这里找到hotspot/src/os/linux/vm/os_linux.cpp,这就要求pthread_mutex_lock(_mutex)...所以在回答你的问题调用wait 可以采取一个互斥我的机器上.请注意,在此之上发生了很多事情,这可能会阻止我们达到这一点.


jta*_*orn 4

wait()并且notify()不进行任何监视器采集。正如这些方法的 javadoc 所述,调用者必须在调用之前获取监视器。事实上,wait()实际上释放了调用者获取的监视器(尽管,我想从技术上讲,等待在最终返回之前确实进行了监视器(重新)获取)。