Java 当等待的线程收到通知时,另一个线程是否可以进入监视器?

Java 当等待的线程收到通知时,另一个线程是否可以进入监视器?,java,concurrency,Java,Concurrency,我正在研究Java并发性,发现了一个我无法回答的有趣问题 例如,我有三个线程:ThreadA、ThreadB和ThreadC。ThreadA进入监视器,并调用wait()方法。然后ThreadB进入同一监视器,调用notify()方法,并在一段时间内继续拥有监视器。当ThreadB拥有监视器时,ThreadC也会尝试获取监视器。我的问题是,当ThreadB释放监视器时,ThreadC是否可以比ThreadA更早地获取监视器?如果可以,为什么?复制它应该遵循哪些条件?根据对象上的Javadoc.n

我正在研究Java并发性,发现了一个我无法回答的有趣问题


例如,我有三个线程:ThreadA、ThreadB和ThreadC。ThreadA进入监视器,并调用wait()方法。然后ThreadB进入同一监视器,调用notify()方法,并在一段时间内继续拥有监视器。当ThreadB拥有监视器时,ThreadC也会尝试获取监视器。我的问题是,当ThreadB释放监视器时,ThreadC是否可以比ThreadA更早地获取监视器?如果可以,为什么?复制它应该遵循哪些条件?

根据对象上的Javadoc.notify():

唤醒的线程将以通常的方式与任何其他线程竞争,这些线程可能正在积极竞争以在此对象上同步;例如,唤醒的线程在成为下一个锁定此对象的线程时没有可靠的特权或缺点

因此,存在ThreadC在ThreadA之前拥有监控器的可能性。没有定义任何线程进入/获取监视器的顺序,也没有任何优先级或公平机制用于标准同步。它真正保证的是,对于给定的锁对象,一次只有on线程在同步块中

考虑到这一事实,仔细的设计应该考虑线程如何获得锁以及锁的使用时间。重复尝试获取锁(获取然后释放,然后再次获取)的线程可能会导致另一个线程被无限期锁定(称为线程饥饿)


使用带有公平性策略的
ReentrantLock
可以以一定的性能代价(比传统的同步稍慢)部分克服此问题。

非常感谢,它帮助了我!