Java 线程状态转换,从 WAITING 到 BLOCKED,还是 RUNNABLE?

Java thread state transition, WAITING to BLOCKED, or RUNNABLE?

SO 共识与互联网上几乎每个 Java 线程状态图之间似乎存在差异;具体来说,关于调用 notify()notifyAll() 之后的线程状态转换 from WAITING...

所以对 SO 的共识是:线程在调用 notify()notifyAll() 后从 WAITING 转换到 BLOCKED;下图以绿色说明了这种转变。

问题

为什么大多数 state diagrams on the web 说明了从 WAITINGRUNNABLE 的过渡,而不是 BLOCKED?红色的描述表示不正确的过渡;我错过了什么吗?

任何显示 notify 将线程从 WAITING 变为 RUNNABLE 的调用的图表都是错误的(或者使用了未阐明的快捷方式)。一旦线程从 notify(或者甚至是虚假唤醒)中被唤醒,它就需要重新锁定它正在等待的对象的监视器。这是BLOCKED状态。

Thread state for a thread blocked waiting for a monitor lock. A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method or reenter a synchronized block/method after calling Object.wait.

这在 Object#notify() 的 javadoc 中有解释:

The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object.

Object#wait()

The thread then waits until it can re-obtain ownership of the monitor and resumes execution.

最近在关注这个问题

正如 Oracle 文档 Thread.State 所说,我们可以使用 LockSupport.park() 将当前线程置于 'WAITING' 或 'TIMED_WAITING' 状态。

所以当您尝试 LockSupport.unpark() 时,指定的线程将从 'WAITING'/'TIMED_WAITING' return 到 'RUNNABLE'。 (不知道会不会经过'BLOCKED'状态)

一个线程处于WAITING状态,进入BLOCK状态,直到通过notify获取monitor变为RUNNABLE

同样适用于 TIMEDWAITING,它进入 BLOCK 状态,如果监视器被其他线程占用,即使指定的时间已经passed.(你的图需要更正)

值得一提的是,在 WAITING 状态下 Thread.interrupt() 方法在 lock.wait() 方法中也是如此。

Thread.interrupt() 方法首先让 WAITING 线程 BLOCKEDisInterrupted 标志设置为 true,只有在重新获取锁中断线程后才能抛出 InterruptedException (这是显而易见的,因为它不能处理异常,通过之前没有独占锁的继续执行)。 (example here)

简单的说

总是WAITING -> BLOCKED能够再次竞争锁,然后最终获得它和运行它的代码RUNNABLE