Google Groupes n'accepte plus les nouveaux posts ni abonnements Usenet. Les contenus de l'historique resteront visibles.

wait vs. yield?

748 vues
Accéder directement au premier message non lu

Marcin Rodzik

non lue,
29 mai 2010, 12:45:5329/05/2010
à
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?

Owen Jacobson

non lue,
29 mai 2010, 13:43:0129/05/2010
à

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

markspace

non lue,
29 mai 2010, 14:41:4829/05/2010
à
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 Rodzik wrote:
> 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.

Eric Sosman

non lue,
29 mai 2010, 15:42:3529/05/2010
à
On 5/29/2010 12:45 PM, Marcin Rodzik wrote:
> 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.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Marcin Rodzik

non lue,
30 mai 2010, 14:25:2430/05/2010
à
On May 29, 9:42 pm, Eric Sosman <esos...@ieee-dot-org.invalid> wrote:
>      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

Joshua Cranmer

non lue,
30 mai 2010, 17:14:3930/05/2010
à

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.

--
Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth

Eric Sosman

non lue,
30 mai 2010, 18:06:4630/05/2010
à
On 5/30/2010 2:25 PM, Marcin Rodzik wrote:
> On May 29, 9:42 pm, Eric Sosman<esos...@ieee-dot-org.invalid> wrote:
>> 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?

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.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Le message a été supprimé

Bent C Dalager

non lue,
30 mai 2010, 18:36:2830/05/2010
à
On 2010-05-30, Marcin Rodzik <marten...@o2.pl> wrote:
> On May 29, 9:42�pm, Eric Sosman <esos...@ieee-dot-org.invalid> wrote:
>> � � �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?

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

Cheers,
Bent D
--
Bent Dalager - b...@pvv.org - http://www.pvv.org/~bcd
powered by emacs

Robert Klemme

non lue,
31 mai 2010, 12:53:0531/05/2010
à
On 31.05.2010 00:06, Eric Sosman wrote:
> On 5/30/2010 2:25 PM, Marcin Rodzik wrote:
>> On May 29, 9:42 pm, Eric Sosman<esos...@ieee-dot-org.invalid> wrote:
>>> 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?
>
> 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

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

markspace

non lue,
31 mai 2010, 14:27:0131/05/2010
à
Robert Klemme wrote:

> On 31.05.2010 00:06, Eric Sosman wrote:
>> In short, I can't think of a portable reason to use yield() --

> 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.

Stanimir Stamenkov

non lue,
31 mai 2010, 17:17:4431/05/2010
à
30 May 2010 22:15:14 GMT, /Stefan Ram/:

> Eric Sosman<eso...@ieee-dot-org.invalid> writes:
>
>> 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.

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.

--
Stanimir

Owen Jacobson

non lue,
31 mai 2010, 23:39:5331/05/2010
à

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

Patricia Shanahan

non lue,
1 juin 2010, 11:48:1101/06/2010
à
Joshua Cranmer wrote:
...

> 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.
>

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.

Patricia

Robert Klemme

non lue,
1 juin 2010, 13:31:0201/06/2010
à

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.

Daniel Pitts

non lue,
1 juin 2010, 16:46:5301/06/2010
à
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/>


--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Robert Klemme

non lue,
1 juin 2010, 17:49:0501/06/2010
à

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/

Arne Vajhøj

non lue,
1 juin 2010, 19:26:1901/06/2010
à
On 01-06-2010 11:48, Patricia Shanahan wrote:
> 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

Stanimir Stamenkov

non lue,
2 juin 2010, 02:53:5602/06/2010
à
Tue, 01 Jun 2010 19:31:02 +0200, /Robert Klemme/:

> On 31.05.2010 23:17, Stanimir Stamenkov wrote:
>> 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.
>> (...)

>> 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.

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.

--
Stanimir

Ian Shef

non lue,
3 juin 2010, 17:13:1703/06/2010
à
Daniel Pitts <newsgroup....@virtualinfinity.net> wrote in
news:ZkeNn.21080$7d5....@newsfe17.iad:

<snip>


>
> 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?

Peter Duniho

non lue,
3 juin 2010, 23:05:2703/06/2010
à

I don't have the book, and can't comment on the specifics of yield(),
though your description sounds reasonable to me.

On the topic of sleep(), on Windows the difference between a sleep of 0
ms and a sleep of 1 ms is that a 0 ms sleep yields only to threads of
the same priority (higher priority threads will have pre-empted
already), while 1 ms sleep will yield to any runnable thread.

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).

Pete

Arne Vajhøj

non lue,
6 juin 2010, 22:29:5006/06/2010
à
On 03-06-2010 23:05, Peter Duniho wrote:
> 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

Ian Shef

non lue,
7 juin 2010, 15:21:1307/06/2010
à
Ian Shef <inv...@avoiding.spam> wrote in
news:Xns9D8C90AB76BE...@138.125.254.103:

> Daniel Pitts <newsgroup....@virtualinfinity.net> wrote in
> news:ZkeNn.21080$7d5....@newsfe17.iad:
>
> <snip>
>>
>> I strong suggest reading Java Concurrency In Practice.
>> <http://virtualinfinity.net/wordpress/technical-book-recommendations/jav

>> a -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 follow-up to my own follow-up...

In the book by Brian Goetz with Tim Peierls, Joshua Bloch, Joseph Bowbeer,
David Holmes and Doug Lea, Java Concurrency in Practice, 6th Printing,
March 2008

Footnote 5 on page 218 (Section 10.3.1 Starvation)

"The semantics of Thread.yield (and Thread.sleep(0)) are undefined [JLS
17.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 JVM implementations yield in this way."

In the book by Joshua Bloch, Effective Java, Second Edition, 4th Printing,
September 2008

Page 287 (Item 72: Don't depend on the thread scheduler)

"Thread.yield has no testable semantics."

...

"In the first edition of this book, it was said that the only use most
programmers would have for Thread.yield was to artificially increase the
concurrency for testing. The idea was to shake out bugs by exploring a
larger fraction of the program's statespace. This technique was once quite
effective, but it was never guaranteed to work. It is within specification
for Thread.yield to do nothing at all, simply returning control to its
caller. Some modern VMs actually do this. Therefore, you should use
Thread.sleep(1) instead of Thread.yield for concurrency testing. Do not use
Thread.sleep(0), which can return immediately."


So JCP has part of the information, but EJ goes into more detail and is
what I was remembering. I have both books and I am trying to learn from
them, but I don't necessarily remember which nuggets of information are
from which book.


0 nouveau message