wait vs. yield?

M

Marcin Rodzik

I've looked at this: http://bit.ly/9GqZoT but still have some
doubts... I'm implementing a thread pool containing multiple threads,
which are created when the application starts, and then they hang
around waiting to be given a job to do. It involves a loop as follows
or similar:

while (true) {
while (job == null)
// wait
// and then do the job:
job.run();
job = null; // the job is done
}

Another method exist to submit the job to this pool thread. It means a
method which perform the assignment:
job = new SomeJobToDo();

The problem is how to perform the "wait" operation. For just poor
esthetic reasons I prefer using the Thread.yield() or eg.
Thread.sleep(500) method. But examples I found in the Internet tend to
use another object (let's say lock) and its Object.wait() method. This
causes that the Object.notify() method must be invoked after ordering
the job (the assignment).

My questions:
1) Which one of these two basic methods is better and, which is more
important for my, WHY?
2) What is better: using sleep or yield in the first method?
 
O

Owen Jacobson

I've looked at this: http://bit.ly/9GqZoT but still have some
doubts... I'm implementing a thread pool containing multiple threads,
which are created when the application starts, and then they hang
around waiting to be given a job to do. It involves a loop as follows
or similar:

while (true) {
while (job == null)
// wait
// and then do the job:
job.run();
job = null; // the job is done
}

Another method exist to submit the job to this pool thread. It means a
method which perform the assignment:
job = new SomeJobToDo();

The problem is how to perform the "wait" operation. For just poor
esthetic reasons I prefer using the Thread.yield() or eg.
Thread.sleep(500) method. But examples I found in the Internet tend to
use another object (let's say lock) and its Object.wait() method. This
causes that the Object.notify() method must be invoked after ordering
the job (the assignment).

My questions:
1) Which one of these two basic methods is better and, which is more
important for my, WHY?
2) What is better: using sleep or yield in the first method?

Don't write your own thread pool. You're reinventing
java.util.concurrent.ExecutorService -- you probably want something
along the lines of

ExecutorService threadPool = Executors.newCachedThreadPool();
// ...

/* SomeJobToDo implements Runnable */
threadPool.submit(new SomeJobToDo());
/* or */

/* SomeJobToDo implements Callable<MyResultType> */
Future<MyResultType> resultFuture =
threadPool.submit(new SomeJobToDo());
// ...
MyResultType result = resultFuture.get();

Hope that helps,
-o
 
M

markspace

Owen is 100% correct. You should not try to write your own thread pool.
There are already working versions which will be much easier for you
to use.

However, I'll assume you are a student and trying to learn. Therefore:


Marcin said:
My questions:
1) Which one of these two basic methods is better and, which is more
important for my, WHY?
2) What is better: using sleep or yield in the first method?


wait() is 100% superior. Both yield() and sleep() means the thread
continues to run, consuming resources. If a thread does nothing, but
still runs, you'll slow the CPU down and other tasks trying to do real
work will be very slow, since they can't get the CPU they need. If you
make a thread POOL of threads that still consume CPU time, then you have
lots of CPU time dedicated to doing nothing. This is even worse.

Also, sleep() is not as responsive as wait() (In more technical terms,
the latency is higher.) sleep() will always wait at least as long as
the value you give it. So if a thread pool has a sleeping thread, and
you give it a task to run, the thread pool will still sleep, and only
wake up later and then run the job. This makes sleep a slow solution.

wait() on the other had does not delay. Even though it's not
guaranteed, the operating system "knows" that a waiting thread wants to
be woken up as soon as possible, and so makes an effort to get it going
as fast as it can. Thus wait is a much faster solution than either
sleep() or yeild(). And wait() consumes no CPU when it is waiting, so
your OTHER threads run faster.

Overall, wait() is really the only solution. sleep() and yield() aren't
even second class solutions, their more like third or fourth class
solutions. Actually, yield() is probably more like a 100th class
solution. Don't use that to implement a waiting worker thread, its far
far worse than sleep() because it really runs a lot more than sleep()
and consumes a LOT more CPU.

If you do need timing like sleep(), wait() takes a time out:

wait( 100 ); // wait 100 milliseconds

This might help you out in some situations.
 
E

Eric Sosman

I've looked at this: http://bit.ly/9GqZoT but still have some
doubts... I'm implementing a thread pool containing multiple threads,

In other words, as Owen Jacobson points out, you're reinventing
the wheel. Why? Are you hoping to make it squarer?
[...]
The problem is how to perform the "wait" operation. For just poor
esthetic reasons I prefer using the Thread.yield() or eg.
Thread.sleep(500) method. But examples I found in the Internet tend to
use another object (let's say lock) and its Object.wait() method. This
causes that the Object.notify() method must be invoked after ordering
the job (the assignment).

My questions:
1) Which one of these two basic methods is better and, which is more
important for my, WHY?

Object.wait() with Object.notify() or Object.notifyAll() is better.
The waiting thread, which can't do anything useful until other threads
have made progress, allows those other threads to use "all" the CPU
cycles and doesn't slow them down. Also, the waiting thread wakes up
"immediately" when there's something for it to do; it doesn't sit idle
while a silly timeout runs its course.
2) What is better: using sleep or yield in the first method?

Thread.sleep() is better than Thread.yield(), because it gives
other threads a chance to use CPU cycles.

Thread.yield() is better than Thread.sleep() because it "notices"
the change of state sooner.

But you're asking whether Holofernes is better than Haman. Both
techniques are *vastly* inferior to wait(). And (again, read Owen
Jacobson's response) all this work has already been done for you, most
likely by someone with greater expertise than you possess at the moment.
 
M

Marcin Rodzik

     Thread.sleep()
     Thread.yield()
Both techniques are *vastly* inferior to wait().

So whay does yield() exist? Is there any case in which it can be
preferred?
Anyway, thanks, I really appreciate your answers.

MR
 
J

Joshua Cranmer

So whay does yield() exist? Is there any case in which it can be
preferred?
Anyway, thanks, I really appreciate your answers.

wait and notify are the Java equivalent to Posix condition
variables--they cause the thread to not run until some condition is met.

Sleep, on the other hand, can be used when you need the thread to not
run for a short while. Yield means to let another thread run if it can
run. The idea is that you might be doing a computationally expensive,
but necessarily synchronous task: every once in a while, you want to
explicitly tell someone else to run.

Sleep is occasionally useful for some timing stuff, and it can be used
in some circumstances to "suggest" certain thread orderings in examples.

Yield is probably much more rarely used, since thread scheduling is
typically rather fair. I can imagine using it before doing something
that would cause a disk cache to be thrashed, or perhaps to tell the
scheduler that it's better to wait for a bit before resuming execution
in heavy usage situations.
 
E

Eric Sosman

So whay does yield() exist? Is there any case in which it can be
preferred?

I can't think of a reason to use yield(), unless you happen to
be writing Java for one specific platform and you know a lot about
how that platform schedules threads. That is, I cannot think of a
way to use yield() and get the same effect on multiple platforms.

On the surface, it *sounds* simple: yield() "causes the
currently executing thread object to temporarily pause and allow
other threads to execute." But how long is "temporarily," and
which "other threads" are eligible to execute? On many systems,
if thread T1 has higher priority than T2 and calls yield(), the
scheduler will take T1 off the CPU and put it right back on again,
since it's the highest-priority runnable thread. At best, you can
hope that all threads with priority equal to T1's will get a chance
to run before T1 gets the CPU again, but even that's not guaranteed.
Low-priority T2 is not likely to get any increase in CPU time because
of a yield() by high-priority T1.

Even if you create T1 and T2 with equal priority (from Java's
point of view), it may turn out that Java's thread priorities do not
map exactly to those of the underlying platform. Many systems, for
example, keep track of a thread's execution history and adjust a
low-level "scheduling priority" to try to improve overall system
throughput. The default scheduling classes in Solaris, for example,
try to raise the priorities of I/O-bound threads and lower those of
CPU-bound threads. Putting the I/O-bound thread first allows it to
start its next I/O sooner so it can be in progress while the CPU-
bound thread executes. In the face of this kind of dynamic priority
adjustment, it becomes difficult to predict whether T1 or T2 has the
higher "effective" priority.

In short, I can't think of a portable reason to use yield() --
maybe somebody smarter than I am knows of one, but I don't. As to
why it exists, I don't really know but I surmise the Java designers
decided to incorporate most of the POSIX Pthreads facilities, and
Pthreads has yield() analogs (with similar drawbacks). We should
consider ourselves lucky, I guess, that they decided to omit the
horrendous Pthreads cancellation mechanisms!

The newsgroup comp.programming.threads is a good place for thread
questions. Some of the people who wrote the Pthreads standards hang
out there, and may be able to tell you why Pthreads' equivalents of
yield() exist. Lots of those people know Java, too.
 
S

Stefan Ram

Eric Sosman said:
Thread.yield() is better than Thread.sleep() because it "notices"
the change of state sooner.

Some years ago in de.comp.lang.java, some people told me,
Thread.yield() was effectively a no-operation, so one should
never use it.
 
B

Bent C Dalager

So whay does yield() exist? Is there any case in which it can be
preferred?

It might be a fossil from an epoch best forgotten, when the JVM used
green threads on some platforms.

Cheers,
Bent D
 
R

Robert Klemme

I can't think of a reason to use yield(), unless you happen to
be writing Java for one specific platform and you know a lot about
how that platform schedules threads. That is, I cannot think of a
way to use yield() and get the same effect on multiple platforms.
In short, I can't think of a portable reason to use yield() --
maybe somebody smarter than I am knows of one, but I don't. As to
why it exists, I don't really know but I surmise the Java designers
decided to incorporate most of the POSIX Pthreads facilities, and
Pthreads has yield() analogs (with similar drawbacks).

That sounds like a good explanation. I would have offered the guess
that maybe some Java mobile platforms need Thread.yield(). I can't
think of another modern platform that would require Thread.yield().

Kind regards

robert
 
M

markspace

That sounds like a good explanation. I would have offered the guess
that maybe some Java mobile platforms need Thread.yield(). I can't
think of another modern platform that would require Thread.yield().


I think Brent likely nailed it. yeild() is legacy code that's there
because someday it might get you out of a jam, and because old time
programmers expect to see it. Java monitors are always preferable, and
if you have Java 1.6 then its concurrency utilities are preferable to
rolling your own classes.
 
S

Stanimir Stamenkov

30 May 2010 22:15:14 GMT, /Stefan Ram/:
Some years ago in de.comp.lang.java, some people told me,
Thread.yield() was effectively a no-operation, so one should
never use it.

I've recently experimented with implementing (Java 1.4 compatible)
asynchronous I/O for copying files using two threads just to see if
it could be any better than FileChannel.transferTo(). I've
basically tried to read into a buffer in one thread, next write it
out in another, while the reading thread fills in a second buffer to
be written next.

Because I've not put much effort into it and I've not done my
synchronization quite right the whole thing basically ended in
reading the whole input while writing quite small (non-consecutive)
part of it. Using Thread.yield() in the reading thread after
reading a block of input made the operation complete normally for me
because it gave chance to the writing thread perform some
preconditions for the synchronization I was relying to.

However, as Eric Sosman has pointed out in another reply,
Thread.yield() is not a way to achieve synchronization because if
there are more (most probably unrelated) threads, it is not
guaranteed which one of them will be run after pausing the current
thread. But it does work (is not a NOP) and I think it could be
used as minor hint for fine-tuning heavy background processes and
the like.
 
O

Owen Jacobson

So whay does yield() exist? Is there any case in which it can be
preferred?
Anyway, thanks, I really appreciate your answers.

MR

It all eventually makes its way down to the OS's scheduler, which hands
out timeslices to processes and threads.

..sleep(n) says "I'm done with my timeslice, and please don't give me
another one for at least n milliseconds." The OS doesn't even try to
schedule the sleeping thread until requested time has passed.

..yield() says "I'm done with my timeslice, but I still have work to
do." The OS is free to immediately give the thread another timeslice,
or to give some other thread or process the CPU the yielding thread
just gave up.

..wait() says "I'm done with my timeslice. Don't give me another
timeslice until someone calls notify()." As with sleep, the OS won't
even try to schedule your task unless someone calls notify (or one of a
few other wakeup scenarios occurs).

Threads also lose the remainder of their timeslice when they perform
blocking IO and under a few other circumstances. If a thread works
through the entire timeslice, the OS forcibly takes control roughly as
if .yield() had been called, so that other processes can run.

You rarely need yield, but if you have a compute-heavy app with logical
task boundaries, inserting a yield *might* improve system
responsiveness (at the expense of time -- context switches, even just
to the OS and back, aren't free). Measure and test against goals you
care about, as always.

-o
 
R

Robert Klemme

30 May 2010 22:15:14 GMT, /Stefan Ram/:

I've recently experimented with implementing (Java 1.4 compatible)
asynchronous I/O for copying files using two threads just to see if it
could be any better than FileChannel.transferTo(). I've basically tried
to read into a buffer in one thread, next write it out in another, while
the reading thread fills in a second buffer to be written next.

Because I've not put much effort into it and I've not done my
synchronization quite right the whole thing basically ended in reading
the whole input while writing quite small (non-consecutive) part of it.
Using Thread.yield() in the reading thread after reading a block of
input made the operation complete normally for me because it gave chance
to the writing thread perform some preconditions for the synchronization
I was relying to.

However, as Eric Sosman has pointed out in another reply, Thread.yield()
is not a way to achieve synchronization because if there are more (most
probably unrelated) threads, it is not guaranteed which one of them will
be run after pausing the current thread. But it does work (is not a NOP)
and I think it could be used as minor hint for fine-tuning heavy
background processes and the like.

What you describe is merely a workaround since you said yourself that
you did the synchronization improperly. I'd rather do a proper
implementation which does not need such hacks. My 0.02EUR.

Kind regards

robert
 
D

Daniel Pitts

What you describe is merely a workaround since you said yourself that
you did the synchronization improperly. I'd rather do a proper
implementation which does not need such hacks. My 0.02EUR.

Kind regards
Also, yield() does nothing for the "happens-before" relationship of any
two threads. In other words, there may still be memory barriers and
other synchronization issues not prevent by yield().

I strong suggest reading Java Concurrency In Practice.
<http://virtualinfinity.net/wordpress/technical-book-recommendations/java-concurrency-in-practice/>
 
R

Robert Klemme

Also, yield() does nothing for the "happens-before" relationship of any
two threads. In other words, there may still be memory barriers and
other synchronization issues not prevent by yield().

I strong suggest reading Java Concurrency In Practice.
<http://virtualinfinity.net/wordpress/technical-book-recommendations/java-concurrency-in-practice/>

I found Doug Lea's "Concurrent Programming in Java" very good. Plus, he
created large parts of java.util.concurrent.* - from the source so to say.

http://g.oswego.edu/

Kind regards

robert
 
A

Arne Vajhøj

I have considered another use for yield. During testing of shared memory
code, it might be useful to scatter a few yield calls at random
locations. If the synchronization is correct, they will make no
functional difference. If there is a bug, they may allow an otherwise
rare context switch to bring it out.

As usual bug => sync problem but no bug => ?.

Arne
 
S

Stanimir Stamenkov

Tue, 01 Jun 2010 19:31:02 +0200, /Robert Klemme/:
What you describe is merely a workaround since you said yourself that
you did the synchronization improperly. I'd rather do a proper
implementation which does not need such hacks. My 0.02EUR.

I was merely pointing out Thread.yield() is not effectively a
no-operation and there are use cases for it, but surely not for
synchronization. I don't think we disagree.
 
I

Ian Shef

I strong suggest reading Java Concurrency In Practice.
<http://virtualinfinity.net/wordpress/technical-book-recommendations/java
-concurrency-in-practice/>

I don't have the book in front of me, but if I recall correctly:

The book tells you to avoid yield(). It has no testable semantics, and
may be implemented as a NO-OP.

Instead, use sleep(...). However, don't use sleep(0), use sleep(1).

I am at work, my book is at home. Maybe someone with immediate access to the
book can comment?
 
A

Arne Vajhøj

Perhaps Java has a similar thread scheduler (and inasmuch as it may just
delegate thread scheduling to the OS, though it doesn't have to, it
would of course inherit that behavior when running Java on Windows).

The Java standard does not mandate anything.

But as far as I know, then all Java implementation on
normal desktop/server platforms the last decade has
been using native threads and not green threads.

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top