RE: JavaMemoryModel: Guaranteed semantics for Thread.yield()

From: Jerry Schwarz (jschwarz@us.oracle.com)
Date: Wed Jan 02 2002 - 12:54:50 EST


At 08:39 AM 1/2/2002, Bill Pugh wrote:

>>But your original informal statement is much stronger. It is imposing
>>requirements on Thread.yield not on the compiler. Imposing requirements
>>on Thread.yield is something I continue to object to.
>>
>>It seems that this restatement in terms of compiler transformations is
>>approximately: when a thread does a yield it can't be holding more locks
>>than the plain semantics would allow. That is something I don't object to.
>
>In general, I think it is a horrible idea to define semantics in terms of
>allowed compiler transformations. The problem is that you never know when
>some combination of other compiler transformation might cause the same bad
>behavior as the banned compiler transformation, or when you might be
>forbidding a transformation needlessly. For example, would it be legal to
>transform a program so that a yield was holding more thread-local locks
>than originally? I believe it should be legal.
>
>Instead, we should define the semantics in terms of the allowed behaviors
>of programs.

I agree. The correct method is to describe behaviors and consider the
consequences. Our difference seems to be over what kinds of statements
about behavior we should be considering. I am objecting to statements
involving fairness of scheduling.

>Plus your suggestion doesn't address yielding loops with volatile
>variables. Do you think the following code should be guaranteed to terminate?
>
>Example 1:
>Initially, volatile x = 0
>
>Thread 1:
>while (x == 0) {
> Thread.yield();
> }
>
>Thread 2:
>x = 1

No I do not. Unless you impose some fairness requirement, there is no
reason to believe that Thread 2 will ever run. I think the specification of
yield requires that some other thread besides thread 1 will make progress,
although even that is unclear. But unless the above are the only threads
in the system there is no guarantee that thread 2 will run.

Thread.yield is essentially a nop. In practical systems it is important,
but from the point of view of the semantics of the Java it is a nop.

The way to give semantics to thready code is to give semantics to
individual threads and then say how you combine individual threads to give
a larger unit (call it a "super thread"). Whey you do that with the above,
and you combine the above threads into a super thread it would not be
reasonable to require thread 2 to execute a step every time thread 1 yields.

>Also, please note that I'm not suggesting that yield or sleep have any
>visibility semantics. Performing a yield/sleep does not mean you have to
>flush/reload variables from registers or the cache.
>
> Bill

-------------------------------
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel



This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:36 EDT