嗯,我错了 - 以下说明不适用,不适用于我的测试运行。
来自Java Thread邮件列表的这封邮件(wot, no chickens?)已经很老了,实际上它是从1996年9月25日开始的.Peter Welch已经发现:
附上的示例显示通知的帖子确实获得了 放入队列的 back 以重新获得监视器。之前 `wait'方法返回,线程再次排队 监视器(在首次完成后很久就到达的线程后面 那个队列!)。这可能导致无限超车,因此, 线程饥饿。
再次总结一下这种行为:
Thread-1 acquires the monitor lock
Thread-1 sees the condition is not true yet -> wait()
Thread-0 acquires the monitor lock
Thread-2 contends with Thread-0 for the monitor lock
Thread-3 contends with Thread-0 for the monitor lock
Thread-4 contends with Thread-0 for the monitor lock
Thread-5 contends with Thread-0 for the monitor lock
Thread-0 turns the condition to true -> notifyAll();
Thread-0 released the monitor lock
Thread-4 acquires the monitor lock
Thread-4 enjoys his desirable state
Thread-4 releases the monitor lock
Thread-2 acquires the monitor lock
Thread-2 enjoys his desirable state
...
作为第一个等待条件的线程将永远成为第一个重新获得监视器的线程。我已经知道,没有公平保证。然而,对我而言,新鲜的是线程如何重新获得监视器的某种顺序。
为什么第一个线程要重新获得监视器锁定?它的实现方式Thread-1
永远无法通过条件并进入所需的状态。
这种语义是否有一些解释?
重要提示:这个问题不是关于,我是否可以依赖关于我发现的机制。我知道如何记录Java的等待和信号,并明确说明,你不能依赖这个。我感兴趣的是,虚拟机是否以这种方式实现它,是否以这种方式对线程进行排序。
答案 0 :(得分:0)
如果使用Object的wait / notify,则排序将特定于JVM。 notify方法的javadoc声明:
Wakes up a single thread that is waiting on this object's monitor. If any threads are
waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and
occurs at the discretion of the implementation. A thread waits on an object's monitor by
calling one of the wait methods.
但是,ReentrantReadWriteLock
确实支持公平政策,公平模式描述为:
When constructed as fair, threads contend for entry using an approximately arrival
order policy. When the currently held lock is released either the longest-waiting
single writer thread will be assigned the write lock, or if there is a group of reader
threads waiting longer than all waiting writer threads, that group will be assigned the read lock.
答案 1 :(得分:0)
我必须检查文档,但我的理解是,无法保证几个竞争者中的哪个线程会获得锁定。它不是“先出先出”或任何这样的确定性排序。如果希望函数X在函数Y之前执行,则不要创建两个单独的线程。创建一个执行X的线程,然后执行Y.多线程的整个想法是所有这些线程独立运行。如果你问,“我怎么能确保线程1在线程2之前运行?”,你问的是错误的问题。如果thread-1中的代码必须在thread-2中的代码之前运行,那么不要将它们作为两个单独的线程。就像那个老笑话,病人:“医生,每当我这样抱着我的手臂,我就会受到这种可怕的痛苦。”医生:“所以不要把你的手臂放在头顶。”