我正在研究Java并发性,并且我发现了一个我无法回答的有趣问题。
例如,我有三个线程:ThreadA,ThreadB和ThreadC。 ThreadA进入监视器,并调用方法wait()。然后ThreadB进入同一个监视器,调用方法notify()并在一段时间内继续拥有监视器。当ThreadB拥有监视器时,ThreadC也会尝试获取监视器。我的问题是,当ThreadB发布或不发布时,ThreadC是否可以在ThreadA之前获得监视器?如果可以,为什么?应该遵循哪些条件来重现它?
答案 0 :(得分:2)
根据Object.notify()上的Javadoc:
唤醒线程将以通常的方式与可能主动竞争同步此对象的任何其他线程竞争;例如,唤醒线程在下一个锁定此对象的线程中没有可靠的特权或劣势。
因此ThreadC有可能在ThreadA之前拥有监视器。没有任何线程进入/获取监视器的已定义顺序,也没有任何优先级或公平机制用于标准同步。它真正保证的是,对于给定的锁定对象,只有线程才会立即在同步块中。
鉴于这一事实,仔细的设计考虑应该考虑线程如何获得锁定以及持续多长时间。重复尝试获取锁定(获取然后释放然后再次获取)的线程可能导致另一个线程无限期地被锁定(称为线程饥饿)。
将ReentrantLock
与公平政策结合使用可以部分克服此问题,但需要一定的性能成本(比传统同步略慢)。