另一个线程可以进入监视器,同时通知等待的线程吗?
Can another thread enter a monitor, while the waiting one is notified?
我正在研究 Java 并发性,我发现了一个我无法回答的有趣问题。
比如我有三个线程:ThreadA、ThreadB和ThreadC。 ThreadA 进入监视器,并调用方法 wait()。然后 ThreadB 进入同一个监视器,调用方法 notify() 并在一段时间内继续拥有监视器。当 ThreadB 拥有监视器时,ThreadC 也尝试获取监视器。我的问题是当ThreadB释放它时ThreadC是否可以先于ThreadA获得监视器?如果可以,为什么?需要满足哪些条件才能重现?
根据 Object.notify() 上的 Javadoc:
The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.
因此存在ThreadC 在ThreadA 之前拥有管程的可能性。没有任何线程 enter/obtain 监视器的定义顺序,也没有用于标准同步的任何优先级或公平机制。它真正保证的是对于给定的锁对象,只有 on thread 会立即进入同步块。
考虑到这一事实,设计时应仔细考虑线程如何获取锁以及获取锁的时间。重复尝试获取锁(获取然后释放但随后再次获取)的线程可能导致另一个线程无限期地被锁定(称为线程饥饿)。
使用 ReentrantLock
和公平策略可以部分解决这个问题,但要付出一定的性能成本(比传统同步稍慢)。
我正在研究 Java 并发性,我发现了一个我无法回答的有趣问题。
比如我有三个线程:ThreadA、ThreadB和ThreadC。 ThreadA 进入监视器,并调用方法 wait()。然后 ThreadB 进入同一个监视器,调用方法 notify() 并在一段时间内继续拥有监视器。当 ThreadB 拥有监视器时,ThreadC 也尝试获取监视器。我的问题是当ThreadB释放它时ThreadC是否可以先于ThreadA获得监视器?如果可以,为什么?需要满足哪些条件才能重现?
根据 Object.notify() 上的 Javadoc:
The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.
因此存在ThreadC 在ThreadA 之前拥有管程的可能性。没有任何线程 enter/obtain 监视器的定义顺序,也没有用于标准同步的任何优先级或公平机制。它真正保证的是对于给定的锁对象,只有 on thread 会立即进入同步块。
考虑到这一事实,设计时应仔细考虑线程如何获取锁以及获取锁的时间。重复尝试获取锁(获取然后释放但随后再次获取)的线程可能导致另一个线程无限期地被锁定(称为线程饥饿)。
使用 ReentrantLock
和公平策略可以部分解决这个问题,但要付出一定的性能成本(比传统同步稍慢)。