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

时间:2013-06-23 03:27:58

标签: java multithreading concurrency locking wait

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

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

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

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

5 个答案:

答案 0 :(得分:12)

其他问题主要集中在waitnotify语言的含义上 - 但这似乎不是您的问题所在...您谈论的是互斥体,这是一个实现细节,因此特定于JVM。

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

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

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

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

<强>更新

我意识到说&#34; park&#34;并没有告诉我们多少。停放线程的代码是特定于平台的(并且在名为PlatformEvent的对象中实现,ParkEvent扩展。在openjdk的版本中,我可以在hotspot/src/os/linux/vm/os_linux.cpp找到Linux的公园代码,这会调用pthread_mutex_lock(_mutex) ...所以回答你的问题调用wait 可能在我的计算机上使用互斥锁 。请注意,在此之上发生的很多事情可能会阻止我们达到这一点。

答案 1 :(得分:4)

wait()notify()不进行任何监视器获取。作为这些方法的javadoc状态,调用者必须在调用之前获取监视器。事实上,wait()实际上释放调用者获取的监视器(尽管我猜技术上等待 在最终返回之前监视(重新)获取)。

答案 2 :(得分:1)

wait释放您已经拥有的锁定,以便在其他人调用notify之后的某个时刻重新获取它。这是synchronized提供的锁定机制的补充。基本上,您使用synchronized获取锁定,然后使用waitnotifynotifyAll来控制释放和重新锁定这些锁的方式。

答案 3 :(得分:1)

wait()notify()始终与同步一起使用,因此可以在锁定和同步之间进行比较。像RentrantLock,ReadWriteLock和Synchronization [block,methods]这样的Locks有很大的不同。

  1. 锁定不在内部使用同步wait()notify()需要同步。

  2. 你使用Lock和java.util.concurrent.locks.Condition,它有效地启用了条件锁定,这对于同步实现来说非常繁琐。

  3. 您没有任何同步的tryLock选项,您可以锁定或等待。但是使用Lock界面,您可以选择。

答案 4 :(得分:1)

  

出于好奇,当Java实现wait()和notify()方法时,他们真的只是使用锁吗?   即,wait()获取互斥锁,notify()释放互斥锁,notifyAll()释放所有互斥锁?

很抱歉,但这一切都没有。 :)

  • synchronized关键字获取monitor。即这是一种锁定形式。注意:使用java.util.concurrent.locks.Lock做类似的事情。
  • wait()导致当前线程等待,直到另一个线程调用此对象的notify()方法或notifyAll()方法,或者已经过了指定的时间量。与锁定无关 - 但只能在当前线程当前线程已拥有此对象的监视器(在synchronized块/方法中)时调用此方法
  • notify()唤醒正在等待此对象监视器的单个线程。再次,与锁定无关 - 但只能在当前线程当前线程已拥有此对象的监视器(在synchronized块/方法中)时调用此方法