Prady
Prady

Reputation: 11330

Are Thread.sleep(0) and Thread.yield() statements equivalent?

Are these two statement equivalent?

Thread.sleep(0);
Thread.yield();

Upvotes: 78

Views: 41904

Answers (12)

Eugene
Eugene

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

Boyang
Boyang

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

peter.petrov
peter.petrov

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

Abdulrahman Awwad
Abdulrahman Awwad

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

SKi
SKi

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

Grigor Nazaryan
Grigor Nazaryan

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

Yochai Timmer
Yochai Timmer

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

Neil Coffey
Neil Coffey

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

Vitaliy Liptchinsky
Vitaliy Liptchinsky

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

Michael Borgwardt
Michael Borgwardt

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

Roberto Aloi
Roberto Aloi

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

z  -
z -

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

Related Questions