Thread.sleep() 实现

发布于 2024-12-29 22:45:24 字数 1404 浏览 6 评论 0原文

今天我参加了一次面试,我向应聘者询问了有关 Thread.sleep() 和 Object.wait() 之间区别的常见且基本的问题。我希望他能回答类似这样的问题,但他说这些方法基本上是同样的事情,很可能 Thread.sleep 在其内部使用 Object.wait(),但 sleep 本身不需要外部锁。这并不完全是正确的答案,因为在 JDK 1.6 中该方法具有以下签名。

public static native void sleep(long millis) throws InterruptedException;

但我的第二个想法是,这并没有那么荒谬。可以使用定时等待来达到相同的效果。看一下下面的代码片段:

public class Thread implements Runnable {
       private final Object sleepLock = new Object();

     // other implementation details are skipped

       public static void sleep(long millis) throws InterruptedException {
            synchronized (getCurrentThread().sleepLock){
                getCurrentThread().sleepLock.wait(millis);
            }
        }

在本例中,sleepLo​​ck 是一个专门用于 sleep 方法内的同步块的对象。我假设 Sun/Oracle 工程师了解奥卡姆剃刀原理,因此 sleep 有意有本机实现,所以我的问题是为什么它使用本机调用。

我想到的唯一想法是假设有人可能会找到像 Thread.sleep(0) 这样有用的调用。根据这篇文章,调度程序管理是有意义的:

这具有清除当前线程的量程并将其放入优先级队列末尾的特殊效果。换句话说,所有具有相同优先级(以及更高优先级)的可运行线程将有机会在下一次给定 CPU 时间之前运行。

因此,同步块会带来不必要的开销。

您知道在 Thread.sleep() 实现中不使用定时等待的任何其他原因吗?

Today I had an interview on which I asked candidate quite usual and basic question about the difference between Thread.sleep() and Object.wait(). I expected him to answer something like like this, but he said these methods basically are the same thing, and most likely Thread.sleep is using Object.wait() inside it, but sleep itself doesn't require external lock. This is not exactly a correct answer, because in JDK 1.6 this method have following signature.

public static native void sleep(long millis) throws InterruptedException;

But my second thought was that it's not that ridiculous. It's possible to use timed wait to achieve the same effect. Take a look at the following code snippet:

public class Thread implements Runnable {
       private final Object sleepLock = new Object();

     // other implementation details are skipped

       public static void sleep(long millis) throws InterruptedException {
            synchronized (getCurrentThread().sleepLock){
                getCurrentThread().sleepLock.wait(millis);
            }
        }

In this case sleepLock is an object which is used particularly for the synchronization block inside sleep method. I assume that Sun/Oracle engineers are aware of Occam's razor, so sleep has native implementation on purpose, so my question is why it uses native calls.

The only idea I came up with was an assumption that someone may find useful invocation like Thread.sleep(0). It make sense for scheduler management according to this article:

This has the special effect of clearing the current thread's quantum and putting it to the end of the queue for its priority level. In other words, all runnable threads of the same priority (and those of greater priority) will get a chance to run before the yielded thread is next given CPU time.

So a synchronized block will give unnecessary overhead.

Do you know any other reasons for not using timed wait in Thread.sleep() implementation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

奈何桥上唱咆哮 2025-01-05 22:45:24

人们可以很容易地说奥卡姆剃刀是相反的。假定 JDK 底层的 JVM 的正常/预期实现在大多数情况下将 java“线程”绑定到本机线程,并且使线程休眠是底层平台的基本功能。如果线程代码无论如何都是本机的,为什么还要在 java 中重新实现它呢?最简单的解决方案是使用已有的功能。

其他一些考虑因素:
无竞争同步在现代 JVM 中可以忽略不计,但情况并非总是如此。获取该对象监视器曾经是一项相当“昂贵”的操作。

如果您在 Java 代码中实现线程休眠,并且实现它的方式并不绑定到本机线程等待,则操作系统必须继续调度该线程,以便运行检查是否到了唤醒时间的代码。正如评论中所阐述的那样,对于现代 JVM 上的示例来说,这显然是不正确的,但很难说
1) 首次以这种方式指定 Thread 类时可能已经存在和预期的内容。

2) 如果该断言适用于人们可能想要实现 JVM 的每个平台。

One could easily say Occam's Razor cuts the other way. The normal/expected implementation of the JVM underlying JDK is assumed to bind java 'threads' onto native threads most of the time, and putting a thread to sleep is a fundamental function of the underlying platform. Why reimplement it in java if thread code is going to be native anyway? The simplest solution is use the function that's already there.

Some other considerations:
Uncontested synchronization is negligible in modern JVMs, but this wasn't always so. It used to be a fairly "expensive" operation to acquire that object monitor.

If you implement thread sleeping inside java code, and the way you implement it does not also bind to a native thread wait, the operating system has to keep scheduling that thread in order to run the code that checks if it's time to wake up. As hashed out in the comments, this would obviously not be true for your example on a modern JVM, but it's tough to say
1) what may have been in place and expected at the time the Thread class was first specified that way.
and
2) If that assertion works for every platform one may have ever wanted to implement a JVM on.

娇纵 2025-01-05 22:45:24

您知道在 Thread.sleep() 实现中不使用定时等待的任何其他原因吗?

因为本机线程库提供了完美的睡眠功能: http://www .gnu.org/software/libc/manual/html_node/Sleeping.html

要了解为什么本机线程很重要,请从 http://java.sun.com/docs/hotspot/threads/threads.html

1.1版本基于绿色线程,这里不再介绍。绿色线程是虚拟机内的模拟线程,在 1.2 及更高版本中使用本机操作系统线程模型之前使用。绿色线程在 Linux 上可能一度具有优势(因为您不必为每个本机线程生成一个进程),但自版本 1.1 以来,VM 技术已取得显着进步,并且绿色线程过去所具有的任何优势都被抹去了多年来,性能不断提高。

Do you know any other reasons for not using timed wait in Thread.sleep() implementation?

Because the native thread libraries provide a perfectly good sleep function: http://www.gnu.org/software/libc/manual/html_node/Sleeping.html

To understand why native threads are important, start at http://java.sun.com/docs/hotspot/threads/threads.html

Version 1.1 is based on green threads and won't be covered here. Green threads are simulated threads within the VM and were used prior to going to a native OS threading model in 1.2 and beyond. Green threads may have had an advantage on Linux at one point (since you don't have to spawn a process for each native thread), but VM technology has advanced significantly since version 1.1 and any benefit green threads had in the past is erased by the performance increases over the years.

心如狂蝶 2025-01-05 22:45:24

Thread.sleep() 不会被虚假唤醒提前唤醒。如果使用 Object.wait(),要正确执行此操作(即确保等待足够的时间),您将需要一个循环来查询已用时间(例如 System.currentTimeMillis()),以确保您等待足够的时间。

从技术上讲,您可以使用 Object.wait() 实现 Thread.sleep() 相同的功能,但您需要编写更多代码才能正确实现。

也是一个相关且有用的讨论。

Thread.sleep() will not be woken up early by spurious wakeups. If using Object.wait(), to do it properly (i.e. ensure you wait enough time) you would need a loop with a query to elapsed time (such as System.currentTimeMillis()) to make sure you wait enough.

Technically you could achieve the same functionality of Thread.sleep() with Object.wait() but you would need to write more code do it correctly.

This is also a relevant and useful discussion.

扬花落满肩 2025-01-05 22:45:24

当一个线程调用sleep方法时,该线程将被添加到一个睡眠队列中。如果计算时钟频率为100HZ,则意味着每10ms当前运行的进程就会被中断一次。保留线程的当前上下文后,它将为每个线程减少该值(-10ms)。当它为零时,线程将移至“等待CPU”队列。当时间片到达这个线程时,它就会再次运行。也因为这个并没有立即开始运行,所以实际休眠的时间比它设置的值要大。

When a thread is called the sleep method, the thread will be added into a sleep queue. If the compute clock frequency is 100HZ, that means every 10ms the current running process will be interrupted. After reserve the current context of the thread, then it will decrease the value (-10ms) for each thread. When it comes to zero, the thread will move to "waiting for CPU" queue. When time slice comes to this thread, it will be running again. Also because this which not immediately become running, so the time actually sleeps is larger than the value it set.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文