33

SO共识和网上几乎所有的Java线程状态图似乎都有出入;具体来说,关于从 WAITING之后notify()或被notifyAll()调用的线程状态转换......

  • WAITING永远不会直接进入 RUNNABLE
  • 线程正在等待,直到它被通知......然后它变成BLOCKED......
  • 一旦通知此线程,它将无法运行...这是..阻塞状态。

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

问题

为什么网络上的大多数状态图都说明了从WAITING到的转换RUNNABLE,而不是BLOCKED?红色表示不正确的过渡;我错过了什么吗?

在此处输入图像描述

4

4 回答 4

23

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

线程阻塞等待监视器锁的线程状态。处于阻塞状态的线程正在等待监视器锁进入同步块/方法或调用后重新进入同步块/方法Object.wait

这在以下的 javadoc 中进行了解释Object#notify()

在当前线程放弃对该对象的锁定之前,被唤醒的线程将无法继续。

Object#wait()

然后线程等待直到它可以重新获得监视器的所有权并恢复执行。

于 2015-02-07T04:55:09.133 回答
2

处于WAITING状态的线程进入BLOCK状态,直到它通过 notify 获得监视器并变为RUNNABLE

同样适用于TIMEDWAITING,它进入BLOCK状态,如果监视器被其他线程持有,即使指定的时间已经过去。(您的图表需要更正)

于 2017-07-02T21:01:34.397 回答
0

我最近专注于这个问题。

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

所以当你尝试LockSupport.unpark()时,指定的线程将从'WAITING'/'TIMED_WAITING'返回到'RUNNABLE'。(我不确定它是否会进入“BLOCKED”状态)

于 2015-06-29T16:20:58.737 回答
0

值得一提的是,Thread.interrupt()method during WAITINGstate while in lock.wait()method 也是如此。

Thread.interrupt()方法首先将标志设置为true的WAITING线程BLOCKEDisInterrupted只有在重新获得锁之后,被中断的线程才能抛出InterruptedException(很明显,因为它无法处理异常,所以在没有排他锁的情况下继续执行)。(此处为示例

简单的说

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

于 2021-07-17T14:55:42.847 回答