JDK-5068368 : (thread) Thread.sleep should say "at least as long" and implement this guarantee
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Won't Fix
  • OS: windows_xp
  • CPU: generic
  • Submitted: 2004-06-25
  • Updated: 2017-05-19
  • Resolved: 2005-08-31
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
Original problem description (addressed now: see evaluation):
Users are sometimes reading the javadoc for the two Thread sleep methods
and interpreting it to mean that a program will sleep for *exactly* the
time they are specifying. In reality, all current implementations have an
additional delay before the program resumes execution.  Several bugs have
been filed (and closed) about this.

Current problem description:
The Thread.sleep spec should say that sleep  "Causes the currently executing thread to sleep (temporarily cease execution) for at least the specified number of milliseconds...." (important text is "at least") And the Java SE implementation has rounding policies (e.g. for nanoseconds in sleep's two parameter method) that would not correctly implement this specification change: a code change to implement the "at least" spec properly is also required (see suggested fix).

Comments
EVALUATION Discussion with leading Java concurrency, threading, and realtime experts led to the conclusion that changing the spec with the proposed "at least" wording poses risks to existing users on the one hand and may be impossible to implement with current constraints on Java implementations having to do with retrograde time scenarios on the other. That is, there are limits to detecting the fact that a system's time reference has been moved backwards. This is not to say implementers should not strive to make sleep as precise and accurate as possible. One specific requirement stemming from this change request is that at the point that the granularity of thread scheduling drops further (becomes finer), implementations may need to revisit delay rounding policies to maintain minimal error rates centered around requested delay values. Making the implementation cognizant (self adjusting) in the face of customization of system parameters is an alternative approach. Finally, there is a gap between current Java Language Specification (JLS) version 3.0 section 17.9 (covering Thread.sleep) and current method javadoc. This gap will be eliminated in Java SE 6.0 javadoc. The JLS specification of Thread.sleep is here: http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.9
31-08-2005

SUGGESTED FIX The following is the *start* of a fix. The change to the spec uses the "lies dormant" wording that is popular in some j.u.c classes, and that I like. I like using the phrase "at least" because it implies both a hard lower bound and that this bound may be exceeded. The change to the implementation ensures *at-least* semantics and assumes that only a millisecond granularity timer is currently available (maybe that should be revisited). --- /u/martin/ws/mustang/src/share/classes/java/lang/Thread.java 2004-08-27 15:53:51.631985000 -0700 +++ /u/martin/ws/sleep/src/share/classes/java/lang/Thread.java 2004-07-12 21:54:53.684556000 -0700 @@ -231,9 +231,17 @@ public static native void yield(); /** - * Causes the currently executing thread to sleep (temporarily cease - * execution) for the specified number of milliseconds. The thread - * does not lose ownership of any monitors. + * Causes the currently executing thread to sleep for at least the + * specified number of milliseconds. + * + * <p>The current thread becomes disabled for thread scheduling + * purposes and lies dormant until either: + * <ul> + * <li>the specified waiting time elapses, or + * <li>some other thread {@link Thread#interrupt interrupts} the current + * thread. + * </ul> + * The thread does not lose ownership of any monitors. * * @param millis the length of time to sleep in milliseconds. * @exception InterruptedException if another thread has interrupted @@ -244,11 +252,20 @@ public static native void sleep(long millis) throws InterruptedException; /** - * Causes the currently executing thread to sleep (cease execution) - * for the specified number of milliseconds plus the specified number - * of nanoseconds. The thread does not lose ownership of any monitors. + * Causes the currently executing thread to sleep for at least the + * specified number of milliseconds plus the specified number + * of nanoseconds. * - * @param millis the length of time to sleep in milliseconds. + * <p>The current thread becomes disabled for thread scheduling + * purposes and lies dormant until either: + * <ul> + * <li>the specified waiting time elapses, or + * <li>some other thread {@link Thread#interrupt interrupts} the current + * thread. + * </ul> + * The thread does not lose ownership of any monitors. + * + * @param millis the length of time to sleep, in milliseconds. * @param nanos 0-999999 additional nanoseconds to sleep. * @exception IllegalArgumentException if the value of millis is * negative or the value of nanos is not in the range @@ -269,11 +286,7 @@ "nanosecond timeout value out of range"); } - if (nanos >= 500000 || (nanos != 0 && millis == 0)) { - millis++; - } - - sleep(millis); + sleep(millis + (nanos > 0 ? 1 : 0)); } /** ###@###.### 2005-04-18 16:58:10 GMT
18-04-2005

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mustang
03-07-2004

EVALUATION I think we have some wording in java.util.concurrent that might be clearer. ###@###.### 2004-06-25 We should postpone this till after Tiger because: - we have some (mild) disagreement about the best wording to use. - Object.wait has exactly the same issues regarding whether the timeout has "approximately correct" or "at least" semantics, and those should be addressed at the same time. - We can't really add "at least" until we fix our implementation to comply with that. Currently we might wake up half a millisecond early in the sleep(millis, nanos) method. It's been this way since 1996. ###@###.### 2004-07-02 Whenever a thread blocks with a timeout, such as with sleep() (but also many other methods in the JDK, e.g. in java.util.concurrent) there is no way to guarantee that the thread will sleep for exactly the desired time period, because of scheduling issues. The only thing it is possible to guarantee (assuming a properly functioning system clock) is that the thread is "dormant" for *at least* the timeout period. Currently the JDK does *not* always comply -- it wakes up early in some situations. Since we *can* make the guarantee of waiting at least for the requested time period, we should. Otherwise, the timeout is nothing more than a hint. ###@###.### 2005-04-18 16:58:10 GMT Following up to the above comment, we can compare the spec for Unix http://www.opengroup.org/onlinepubs/009695399/utilities/sleep.html The sleep utility shall suspend execution for at least the integral number of seconds specified by the time operand. http://www.opengroup.org/onlinepubs/009695399/functions/usleep.html The suspension time may be longer than requested due to the scheduling of other activity by the system. The fact that they use the phrase "at least" lends support to the idea that we should too. ###@###.### 2005-07-20 02:52:05 GMT The clarification aspect of this CR was split off as CR 6312446 to bring the sleep javadoc in line with JLS 17.9 and allow the spec change and implementation change currently proposed by this CR to proceed through the required expert consultation and process, to implement or reject the change. It has also been observed that the spec and implementation changes to Thread.sleep mentioned above naturally apply to varying degrees to similar methods like Object.wait, Thread.join, methods in java.util.concurrent, etc. If this change is approved generalization will be done with one or more additional change requests.
03-07-2004

PUBLIC COMMENTS -
03-07-2004