8

In javadoc there is said that yield method

Causes the currently executing thread object to temporarily pause and allow other threads to execute.

And Katherine Sierra and Bert Bates SCJP book says that

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 what actually method is doing?

Shikarn-O
  • 3,337
  • 7
  • 26
  • 27
  • 1
    I don't see a question here. What don't you understand about the documentation you've quoted? – Matt Ball Mar 01 '11 at 16:07
  • I just think that threads of the same priority don't include threads with priority higher than one, yield methof of what was called – Shikarn-O Mar 01 '11 at 16:10
  • 4
    The source code says it all `public static native void yield();` :p – Johan Sjöberg Mar 01 '11 at 16:12
  • Since I am sure what it does on Windows - calls sleep(0): http://msdn.microsoft.com/en-us/library/ms686298%28v=vs.85%29.aspx IOW: returns the thread to the OS scheduler queue. – bestsss Mar 01 '11 at 16:43
  • 1
    If you place yield() in a busy loop, it will take about 20 micro-seconds on average and it will not pass to another thread 99%+ of the time. A process can pass to another thread at any time, it just makes it more likely to happen where you call yield(). – Peter Lawrey Mar 01 '11 at 17:45
  • @Peter, it depends on the thread priority. I think I need to find some ref. by Doug Lea about as well. http://comments.gmane.org/gmane.comp.java.jsr.166-concurrency/7314 – bestsss Mar 01 '11 at 19:00

7 Answers7

13

Given a multi-threaded application, yield will cause the currently executing thread to pause execution and be set in a waiting state. The JVM will then begin running another thread that was previously in a waiting state.

I believe the same thread that just yielded could technically be scheduled to start again.

And I have yet to see this in the wild though. So I think it is safe to avoid.

To elaborate:

In a multi-threaded environment threads are scheduled and unscheduled off and on at the JVM's will. So, even if yield is not called in code, your thread can/will automatically yield to other threads when the JVM decides it should. This allows multi-threading to work in an environment with only one processing core.

Calling yield simply tells the JVM to put the current thread in a waiting state even if the JVM wasn't going to.

I shall attempt an illustration:
The following is a very simplified illustration of the execution of 2 threads over time (assume 1 core)-

Thread\Time    1    2    3    4    5    6    7    8    9
Thread 1    -----------       -----          -------
Thread 2               -------     ----------       ------

Whenever you see a '-' that means a thread is executing. A ' ' means that the thread is waiting. As you can see, only 1 thread can actually run at a time. So, while 1 runs, the other waits. What yield is intended to do is give other threads a chance to run ahead of the currently running thread.

jjnguy
  • 136,852
  • 53
  • 295
  • 323
  • +1 I've always found it quite useful to think about `yield()` as just a hint to the scheduler. (I know it technically isn't a hint, but in many ways it behaves like one.) – biziclop Mar 01 '11 at 16:16
  • As per Java specification, `yield()` may be a no-op. If you want to force yield, you might want to try `Thread.sleep(1)`. However, only in very rare cases such usage is warranted. – Enno Shioji Mar 01 '11 at 16:22
  • @Enno, are you confirming this line- "I believe the same thread that just yielded could technically be scheduled to start again."? – jjnguy Mar 01 '11 at 16:23
  • @jjnguy: Not necessarily.. the spec says "a yield operation need [not to] have observable effects", so if I were to implement a JVM, I'd get away to to simply ignore (e.g. remove at compile time) any calls to yield, right? Not sure how the actual JVMs are handling yields though. – Enno Shioji Mar 01 '11 at 16:43
  • @Enno, ah, I see what you mean. Ha, that's probably what I'd do too. – jjnguy Mar 01 '11 at 16:44
  • @Enno, do you have an idea which OS executes Thread.yeild as no-op. As for doc: LockSupport.park can be just as much a no-op. See my comment under the question what JVMs do for real. – bestsss Mar 01 '11 at 16:45
  • @jinguy, there a lot of possible no-ops in java, simply no 100% guarantees of the doc/spec. Object.wait can be implemented as no-op and it will be fine. Thread.sleep(1) is a lot worse than Thread.yeild. Thread.yeild can be used during busy waits, say after spinning 128 times, calls Thread.yeild once. – bestsss Mar 01 '11 at 16:47
  • @bestsss, hmmm, interesting. That doesn't help Java's case for write once, run anywhere. – jjnguy Mar 01 '11 at 16:53
  • @jjnguy, which exactly doesn't help? that `wait` can be implemented as no-op? Yes, it is possible, but it's never done. – bestsss Mar 01 '11 at 16:55
  • @bestsss, that different JVMs implement things in different ways. – jjnguy Mar 01 '11 at 16:56
  • @jjnguy, the hardware implications, memory model (usually hardware memory models are weaker than java's) require different approaches, hence the not so strong warrants by the spec. `Thread.yeild` is pretty straightforward to me, though. Returning the thread to the OS should be available on any multithreaded enabled OS. As long as the JVM passes the compatibility tests, there should be no issues. – bestsss Mar 01 '11 at 17:02
  • IMO, in multicore cases, seems some different! – qinxian Jun 12 '13 at 19:00
2

Threads may be in states ready (runnable), blocked (e.g., waiting for some io to finish), or running; this is common to all thread implementations, although some particular implementations may have more states.

Yield causes the thread to change from running to runnable, and wait for the scheduler to change it to running again, in the future. This is what is meant in the SCJP book.

To the thread, it seems like it has been paused for a while, like described in the javadoc. So both statements are correct, just differently phrased.

lasaro
  • 504
  • 3
  • 13
2

yield() is generally used when you are waiting on a thread for something to occur but don't want to block the CPC cycles with something like while(condition){ ...} . The way yield() works differ from platform to platform and depends on the Thread Scheduler and you shouldn't rely on it behaving in a particular way.

Bala R
  • 107,317
  • 23
  • 199
  • 210
2

It originates from the time of cooperative multitasking. The basic idea is, the processor executes only one thread until:

  1. this thread ends
  2. this thread does some blocking operation, like object.wait() or Thread.sleep, waiting on some IO operation to complete, waiting for some object monitor, or similar.
  3. this thread invokes Thread.yield().

In each of this cases the thread scheduler then selects another thread to execute. So, to be fair to other threads, you would in longer loops without any blocking operations regularly call yield(). (If no other thread is ready to run, then the same thread would be scheduled again, so no really big performance loss.)

In modern VMs thread switching can occur on any point, not only these listed, threads may even be executed simultaneously, so it is not really necessary, and some VMs may ignore it altogether (similar to System.gc().)

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
  • you have omitted any blocking IO and LockSupport.park, where a thread can bail out – bestsss Mar 01 '11 at 16:51
  • @bestsss: Blocking IO is mentioned ("waiting on some IO operation to complete"), and LockSupport.park is included in "or similar". But I think this method (and class) did not yet exist when yield() was necessary. – Paŭlo Ebermann Mar 01 '11 at 16:56
  • ŭlo, my bad, the IO has slipped away in my mind. LockSupport was introduced in 1.5 (the method effectively calls `Unsafe.park`), Thread.yeild has been available since Java's inception. – bestsss Mar 01 '11 at 17:06
2

yield() method is there to make sure that all same priority threads in a application would not cause starvation. For e.g. five threads are there in a application and all of them are of same priority. Now suppose one thread got chance to run and this thread is taking so long to complete its task and hence other threads wont get chance to run. So to avoid this kind of situations yield() is there to rescue.

Umesh K
  • 13,436
  • 25
  • 87
  • 129
2

Ultimately, the call to yield() results in calling os methods like this, which in principle would put the task itself back in to the run queue and let the next task run (source):

 /**
  * sys_sched_yield - yield the current processor to other threads.
  *
  * This function yields the current CPU to other tasks. If there are no
  * other threads running on this CPU then this function will return.
  */
 SYSCALL_DEFINE0(sched_yield)
 {
        /*
         *  lock this runqueue and disable interrupts.
         */
         struct rq *rq = this_rq_lock();

         schedstat_inc(rq, yld_count);
         current->sched_class->yield_task(rq);

         /*
          * Since we are going to call schedule() anyway, there's
          * no need to preempt or enable interrupts:
          */
         __release(rq->lock);
         spin_release(&rq->lock.dep_map, 1, _THIS_IP_);
         _raw_spin_unlock(&rq->lock);
         preempt_enable_no_resched();

         schedule();

         return 0;
 }
Enno Shioji
  • 26,542
  • 13
  • 70
  • 109
0

Hope it helps!

package yield;

public class ThreadYieldApp {

    Thread th1 = new Thread("Thread 1") {
        public void run() {

            for(int i = 0; i <= 10; i++) {
                System.out.println("Before Yield - " + Thread.currentThread().getName() + " at index - " + i);
                //Currently pauses the thread and checks for other threads of same priority, and passes control to it based on Thread Scheduler pick 
                Thread.yield();
                System.out.println("Currently running - " + Thread.currentThread().getName() + " at index - " + i);
            }
        }
    };

    Thread th2 = new Thread("Thread 2") {
        public void run() {
            for(int i = 0; i <= 10; i++) {
                System.out.println("Currently running - " + Thread.currentThread().getName() + " at index - " + i);
            }
        }
    };


    public static void main(String[] args) {
        ThreadYieldApp threadYieldApp = new ThreadYieldApp();
        threadYieldApp.th1.start();
        threadYieldApp.th2.start();
    }

    //Happy coding -- Parthasarathy S
}
Parthasarathy S
  • 197
  • 1
  • 6