当 Java 线程执行潜在的阻塞操作时,它是否总是丢失当前的 CPU 时间片?
When a Java thread performs a potentially blocking action, does it always loss the current CPU timeslice?
一个潜在的阻塞动作(例如Thread.join(), obj.wait(), monitorEnter)可能会在某些情况下继续执行(例如对于Thread.join(),如果interrupt flag is set by the time of calling, the method won't block. For obj.wait(), if the interrupt flag is seted and monitor is available, the action won't block).在这种情况下,java线程是否会在当前的CPU时间片中继续运行;或者它会释放当前时间片并等待下一次调度?
不能保证它会丢失 CPU,也不能保证它会在整个时间片内被阻塞;
- 可以立即执行操作。
- 该操作可能会在放弃 CPU 之前忙等待一小段时间,但它可能会在那个时间内完成。
- 线程可能会在时间片内取回 CPU。
具体如何工作主要取决于 OS。忙等待策略有时会在Java中实现,在这种情况下你会在源代码中看到它。
你的问题有点混乱——一个线程只有在它已经拥有监视器的情况下才能调用wait。这是通过进入同步块并通过 monitorEnter 过程获得的。
但是试着回答你的问题:如果一个线程调用一个潜在的阻塞动作(即需要获取对象监视器),它是否总是会丢失时间片?答案是不。它会先尝试 "fast path" 次尝试,然后才会停止线程。
VM 首先尝试非常快速的原子 CAS 操作来获取监视器。如果失败,它会尝试一个短自旋锁(以保持 CPU)。如果自旋锁失败,那么它将停放线程。
公园发生在Windows下:http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/os/windows/vm/os_windows.cpp#l4787
它看起来像是在调用 Windows WaitForSingleObject API 函数。
如果anotherThread.join()
被执行,并且anotherThread
已经完成,那么CPU时间片不会丢失。类似地,如果monitorEnter obj
被执行,并且obj
没有被锁定,执行将不间断地继续。
如果您故意要释放当前时间片并等待下一次调度,则调用 Thread.yield()
或 Thread.sleep(0)
,但 JVM 实现可能会忽略您的提示。
一个潜在的阻塞动作(例如Thread.join(), obj.wait(), monitorEnter)可能会在某些情况下继续执行(例如对于Thread.join(),如果interrupt flag is set by the time of calling, the method won't block. For obj.wait(), if the interrupt flag is seted and monitor is available, the action won't block).在这种情况下,java线程是否会在当前的CPU时间片中继续运行;或者它会释放当前时间片并等待下一次调度?
不能保证它会丢失 CPU,也不能保证它会在整个时间片内被阻塞;
- 可以立即执行操作。
- 该操作可能会在放弃 CPU 之前忙等待一小段时间,但它可能会在那个时间内完成。
- 线程可能会在时间片内取回 CPU。
具体如何工作主要取决于 OS。忙等待策略有时会在Java中实现,在这种情况下你会在源代码中看到它。
你的问题有点混乱——一个线程只有在它已经拥有监视器的情况下才能调用wait。这是通过进入同步块并通过 monitorEnter 过程获得的。
但是试着回答你的问题:如果一个线程调用一个潜在的阻塞动作(即需要获取对象监视器),它是否总是会丢失时间片?答案是不。它会先尝试 "fast path" 次尝试,然后才会停止线程。
VM 首先尝试非常快速的原子 CAS 操作来获取监视器。如果失败,它会尝试一个短自旋锁(以保持 CPU)。如果自旋锁失败,那么它将停放线程。
公园发生在Windows下:http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/os/windows/vm/os_windows.cpp#l4787
它看起来像是在调用 Windows WaitForSingleObject API 函数。
如果anotherThread.join()
被执行,并且anotherThread
已经完成,那么CPU时间片不会丢失。类似地,如果monitorEnter obj
被执行,并且obj
没有被锁定,执行将不间断地继续。
如果您故意要释放当前时间片并等待下一次调度,则调用 Thread.yield()
或 Thread.sleep(0)
,但 JVM 实现可能会忽略您的提示。