java线程睡眠解析和等待同步块

Num*_*ron 3 java multithreading sleep thread-sleep

我想更多地了解线程睡眠分辨率的工作原理,以及它与 sleep() 的分辨率无关的内容。

我知道它是由操作系统定义的,而在 Windows 上它通常是 15 毫秒。我最近无法通过环顾四周来确认这一点,但我依稀记得这 15 毫秒是由操作系统循环的,并且对所有线程都是“全局的”,这意味着 15 毫秒不是线程可以休眠的最短时间,而是sleep(1) 的最大值。那正确吗?所有操作系统都一样吗(超出持续时间)?

我想不出这可能很重要的情况,但是线程的虚假唤醒是否总是发生在此睡眠周期的动作点,还是可以随时发生?

在同步块上,等待线程是否有效地休眠(1)并在每个周期检查锁,还是退出块的线程立即唤醒等待线程?这对所有操作系统都一样吗?

当线程在wait()之后被notify()-ed时,它在等待锁定时会以与上面相同的方式处理,还是不同?

从性能的角度来看,还有其他时间 15ms 循环是相关的吗?

Mar*_*mes 5

您需要对多线程内核进行一些研究。

“线程的虚假唤醒是否总是发生在这个睡眠周期的动作点,还是随时可能发生?”

在 Windows 上没有使用 sleep() 或任何内核同步对象等待的虚假唤醒 - 根本没有。任何此类趋势都已在内核中设计,不会传播到用户线程。

如果一个线程正在休眠或等待某个同步对象(如互斥锁或信号量锁),则它根本不会运行 - 它只是内核队列中的一个死的“线程描述符对象”,因此所有与线程相关的东西,数据堆栈等的空间。在睡眠的情况下,TDO 位于所有超时线程的“增量队列”上,按唤醒时间排序,操作系统每 15 毫秒检查一次该队列头部的项目。在定时锁等待的情况下,TDO 位于两个队列 - 超时队列和锁拥有的队列。要么 TDO 将到达计时器队列的头部并在其间隔结束时准备就绪,要么另一个线程将释放锁并使线程准备就绪。无论哪个先到达那里,都获胜,并且 TDO 将从另一个队列中删除。新就绪线程然后加入就绪线程集,并且,

因此,Windows 上的“15ms”由所有线程“共享”。Windows 是桌面操作系统,15ms 超出了人类的直接感觉,因此 99.9% 的家庭线程并不关心,因为它们只需要大超时、等待 I/O、等待一些线程间通信锁或某些组合其中。

“从性能角度来看,15 毫秒循环是否还有其他时间相关?”

不多。计时器重新调度有一个副作用,如果最高优先级的可运行线程集大于可用于运行它们的内核数,则该集以循环方式运行,因为这些线程的列表是圆的。这仅与经常过载的机器相关,并且大多数线程仅使用计时器间隔来超时其他阻塞系统调用。