3

我想更多地了解线程睡眠解析是如何工作的,以及它与简单的 sleep() 解析之外的内容有关。

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

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

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

当线程在等待()之后被通知()时,它在等待锁定时会以与上述相同的方式处理,还是不同?

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

4

2 回答 2

5

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

'线程的虚假唤醒是否总是发生在这个睡眠周期的动作点,或者它可以随时发生?

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

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

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

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

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

于 2012-06-19T06:52:32.500 回答
3

Thread.sleep()实现取决于操作系统。

睡眠的粒度通常受线程调度程序的中断周期限制。在 Linux 中,这个中断周期在最近的内核(2.6.8 以后)中一般为 1ms。在 Windows 中,调度程序的中断周期通常约为 10 或 15 毫秒(我相信这是由处理器决定的),但可以在软件中请求更高的周期,并且 Hotspot JVM 在认为必要时会这样做。

于 2012-06-19T05:36:29.997 回答