Reputation: 11330
Are these two statement equivalent?
Thread.sleep(0);
Thread.yield();
Upvotes: 78
Views: 41904
Reputation: 11085
No, they are not equivalent and besides the explanations above,
I think it's necessary to check the Javadoc of yield
. It seems not a good idea to use yield
unless below situation meets.
It is rarely appropriate to use this method. It may be useful for debugging or testing purposes, where it may help to reproduce bugs due to race conditions. It may also be useful when designing concurrency control constructs such as the ones in the {@link java.util.concurrent.locks} package.
Upvotes: 0
Reputation: 2566
It's platform-and-implementation-dependent, and they are likely not equivalent.
The below snippet, when using Thread.sleep(0), most of the time gives the output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Whereas when using Thread.yield(), mostly gives:
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[0, 2, 2, 2, 2, 2, 2, 2, 2, 2]
See snippet below:
public class CompareSleepZeroAndYield {
private ArrayList<Integer> list1 = new ArrayList<>();
private ArrayList<Integer> list2 = new ArrayList<>();
public ArrayList<Integer> getList1() {
return list1;
}
public ArrayList<Integer> getList2() {
return list2;
}
public CompareSleepZeroAndYield() {
list1.add(0);
list2.add(0);
}
public void tryFieldLock1() {
synchronized (this.list1) {
list1.add(list2.get(list2.size() - 1) + 1);
}
}
public void tryFieldLock2() {
synchronized (this.list2) {
list2.add(list1.get(list1.size() - 1) + 1);
}
}
public static void main(String[] args) {
CompareSleepZeroAndYield obj = new CompareSleepZeroAndYield();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
int count = 10;
while (--count >0) {
obj.tryFieldLock1();
try {
Thread.sleep(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
// compare above and below
// Thread.yield()
}
System.out.println(obj.getList1());
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
int count = 10;
while (--count >0) {
obj.tryFieldLock2();
try {
Thread.sleep(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
// compare above and below
// Thread.yield()
}
System.out.println(obj.getList2());
}
});
t1.start();
t2.start();
}
Upvotes: 2
Reputation: 39477
The famous Brian Goetz's book "Java Concurrency in Practice" (published in 2006 but still fundamentally valid) says the following on this question.
The semantics of Thread.yield and Thread.sleep(0) are undefined [JLS17.9]; the JVM is free to implement them as no-ops or treat them as scheduling hints. In particular, they are not required to have the semantics of sleep(0) on Unix systems — put the current thread at the end of the run queue for that priority, yielding to other threads of the same priority — though some JVMs implement yield in this way.
The rest one can find in the Javadoc pages.
Upvotes: 9
Reputation: 122
Thread.sleep() and Thread.yield() do the same thing except that Thread.yield() relinquishes only to threads running on the same processor in multiprocessor environment.
Upvotes: -1
Reputation: 8476
OpenJDK source (Java SE 7) have the following implementation for Thread.sleep(0)
in JVM_Sleep
function of jvm.cpp:
if (millis == 0) {
// When ConvertSleepToYield is on, this matches the classic VM implementation of
// JVM_Sleep. Critical for similar threading behaviour (Win32)
// It appears that in certain GUI contexts, it may be beneficial to do a short sleep
// for SOLARIS
if (ConvertSleepToYield) {
os::yield();
} else {
ThreadState old_state = thread->osthread()->get_state();
thread->osthread()->set_state(SLEEPING);
os::sleep(thread, MinSleepInterval, false);
thread->osthread()->set_state(old_state);
}
}
And implemtation of Thread.yield() have the following code:
// When ConvertYieldToSleep is off (default), this matches the classic VM use of yield.
// Critical for similar threading behaviour
if (ConvertYieldToSleep) {
os::sleep(thread, MinSleepInterval, false);
} else {
os::yield();
}
So Thread.sleep(0)
and Thread.yield()
may call same system calls in some platforms.
os::sleep
and os::yield
are platform specific stuff.
On both Linux and Windows: os::yield
seems to be much simplier than os::sleep
.
For example: os::yield
of Linux calls only sched_yield()
. And os::sleep
have about 70 lines of code.
Upvotes: 18
Reputation: 577
What yield() is supposed to do is make the currently running thread head back to runnable to allow other threads of the same priority to get their turn. So the intention is to use yield() to promote graceful turn-taking among equal-priority threads. In reality, though, the yield() method isn't guaranteed to do what it claims, and even if yield() does cause a thread to step out of running and back to runnable, there's no guarantee the yielding thread won't just be chosen again over all the others! So while yield() might—and often does—make a running thread give up its slot to another runnable thread of the same priority, there's no guarantee.
A yield() won't ever cause a thread to go to the waiting/sleeping/ blocking state. At most, a yield() will cause a thread to go from running to runnable, but again, it might have no effect at all.
Source: SCJP Sun Certified Programmer book
Upvotes: 0
Reputation: 49261
Thread.Sleep()
has a slightly larger overhead because it creates a system that includes some kind of timer that will wake the process. (Depends on implementation basically)
Bottom line it will call a Yield()
in the end.
Thread.Yield()
Will just give-up the thread's turn, and gain it in the next round.
Thread.Sleep(0)
might have an optimization to just call yield. (Again, implementation)
Upvotes: 0
Reputation: 21815
This really depends on the platform and version of the JVM. For example, under Windows in JDK 5 (Hotspot), yield() is literally implemented as Sleep(0)-- although a sleep of 0 is treated slightly specially by Windows as I recall. But in JDK 6, yield() is implemented as SwitchToThread().
I put together some information a while ago on Thread.yield(), including some implementational details that may be of interest. (You might also want to see the stuff on Thread.sleep() I put together on the same site.)
Upvotes: 35
Reputation: 5299
Thread.Yield can give up CPU resource to threads with lower priorities, while Thread.Sleep(0) gives up CPU only to threads with equal or higher priorities.
At least on Windows platform :)
Upvotes: 0
Reputation: 346407
No. The most obvious difference is that sleep()
throws the (checked) InterruptedException
. In practice, the effect may be almost the same, but it's entirely implementation-dependant.
I'd wager that doing each a million times in a row would take much longer for sleep(), since system timer granularity probably often causes it to actually sleep for a non-negligible amount of time.
Upvotes: 54
Reputation: 30995
yield() tells the JVM Thread Scheduler that it's OK to give other threads time slices. Usually the JVM uses this call to activate another thread of the same thread priority. In a good preemptive multithreading environment, yield() is a no-op. However, it is important in a cooperative multithreading environment, since without yield(), one thread can eat up all of the CPU.
sleep(x) tells the JVM Thread Scheduler to actively put this thread to sleep and not run it again until at least x milliseconds have elapsed.
Neither sleep() nor yield() change anything about the status of synchronization locks. If your thread has a lock, and you call sleep(1000), then at least a second will elapse before your thread wakes up. When it wakes up it may decide to release the lock -- or it may hold on to it longer.
SOURCE: http://www.jguru.com/faq/view.jsp?EID=425624
Upvotes: 10
Reputation: 7178
Yield adds the current thread to the ready queue and allows other threads to run. Sleep is not guaranteed to relinquish the cpu.
Upvotes: 34