wait(),notify() - 哪个线程先解锁?

4
尝试理解wait()notify()。我知道当线程A进入wait()状态时,它将被其他线程的notify()唤醒。
但是,如果线程ABC按照特定顺序进入了wait()状态,会发生什么?谁会被notify()唤醒?根据我的实验,A线程将首先被唤醒。我对吗?
这是否意味着系统知道线程按照哪个顺序进入了wait()状态?

没有这样的保证,请参见https://dev59.com/5ovda4cB1Zd3GeqPXUrq和https://dev59.com/_nVD5IYBdhLWcg3wQZQg。 - Mark Rotteveel
5个回答

8
notify()的文档中可以看到,它会唤醒等待此对象监视器的单个线程。如果有任何线程在等待此对象,则其中一个线程会被选择唤醒。选择是任意的,并由实现自行决定。线程通过调用wait方法等待对象的监视器。一些其他API(例如Semaphore)具有“公平性”概念,您可以确保线程按照它们阻塞的顺序进行处理。

2

Java语言规范第17.2.2节通知

不能保证选择等待集中的哪个线程。

因此,观察到的行为不能保证并且不应该依赖它。


2
不,虚拟机不知道线程处于等待状态的顺序。当您调用notify()时,其中一个线程将返回到活动/可运行状态,并且无法知道虚拟机会选择哪个线程。有时,它们可以按照它们被放置在等待状态的顺序运行,但是规范不能保证这一点。因此,在不同的虚拟机中,您可能会得到完全不同的结果,甚至在同一虚拟机中,如果您多次运行代码。

1
那是不正确的 - OP 正在谈论 notify() ,而该方法只能将一个线程置于可运行状态。你一定想到了 notifyAll() - Erwin Bolwidt
谢谢@ErwinBolwidt,你是对的,我刚刚纠正了答案。我在考虑notifyAll()。 - Alessandro Moraes

1

不,关于顺序没有保证。notify方法的javadoc非常清楚:

唤醒等待在此对象监视器上的单个线程。如果有任何线程正在等待此对象,则选择其中一个进行唤醒。 选择是任意的,并且由实现自行决定。线程通过调用wait方法等待对象的监视器。


1

没有这样的顺序。任何一个线程都有平等的机会进入可运行状态。实际上,JVM/OS只能将它们视为一组等待线程,它们不知道任何顺序。

就你的实验而言,为了得出公正的结论,实际上你需要进行大量次数的实验。

在线程中,你可以期望有一个顺序(先进先出),只有当你使用类似于信号量的东西时。然后这些线程被放入等待队列,先来者先服务。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接