2012-06-19 54 views
3

我想知道更多关于线程睡眠解决方案是如何工作的,以及除了简单地解析睡眠()之外,它还与什么关联。java线程睡眠解决方案和等待同步块

我知道它是由操作系统定义的,在Windows上它的定义是典型的15ms。我还没有能够通过最近环顾四周来证实这一点,但我隐约记得这个15ms是由操作系统环绕的,并且对所有线程都是“全局”的,这意味着线程可以睡眠的最短时间不是15ms,而是最大的睡眠(1)。是对的吗?所有操作系统是否都一样(超出期限)?

我不能想到这可能很重要的情况,但是会在这个睡眠周期的行动点发生线程的虚假唤醒,还是会随时发生?

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

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

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

回答

4

你需要对多线程内核做一点研究。

'会在这个睡眠周期的动作点发生线程的虚假唤醒,还是可以随时发生?

没有虚假的睡眠唤醒()或任何内核同步对象在Windows上等待 - 根本没有。任何这样的倾向已经被设计在内核中,并且不会传播到用户线程。

如果一个线程正在睡眠或等待某个同步对象(如互斥锁或信号量锁),则该线程根本无法运行 - 它仅仅是内核队列中的死亡“线程描述符对象”相关的东西,堆栈的数据空间等等。在睡眠的情况下,TDO在所有超时线程的'delta队列'上,按唤醒时间排序,并且OS每隔一个队列头检查项目为15ms。在定时锁定等待的情况下,TDO处于两个队列 - 超时队列和锁拥有的队列。当TDO的时间间隔到时,TDO会到达定时器队列的头部并准备就绪,或者另一个线程将释放锁定并使线程就绪。无论首先到达那里,胜利,并且TDO从另一个队列中移除。新准备好的线程然后加入准备好的线程集合,并且如果有可用的核心或者可以抢占较低优先级的线程,则新准备好的线程被分派到核心上。

因此,Windows上的'15ms'是所有线程'共享'的。 Windows是一个桌面操作系统,15ms超越了人类的直觉,所以99.9%的家庭线程并不在意,因为它们只需要很长的超时时间,正在等待I/O,正在等待某些线程间通信锁定或某种组合它们。

'有没有其他时间15ms循环与性能角度相关?

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

+0

谢谢,这清理了很多。我应该注意到sleep()的另一个常见用法是分解繁忙的循环来融化你的cpu。在这种情况下15ms意味着循环将仅执行〜66次/秒,这可能根据应用产生人类显着的差异。 – Numeron

+0

@Numeron - 你需要更大的风扇/散热器。没有什么 - 我用过的所有盒子都可以平放。我可以听到风扇的速度随着所有内核完全加载CPU而增加,但没有什么不好的事情发生。 –

+0

台式机很好,但在笔记本电脑上它可能是一个严重的问题。 – Numeron

3

Thread.sleep()实施依赖于操作系统。

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

+0

当你说它的操作系统依赖于什么部件到底是什么意思?只是超时时间,或更多?您是否也提到了每个线程独特的10-15毫秒和共享的10-15毫秒循环之间的差异?等待锁定的线程是否也取决于操作系统? – Numeron