Re: JavaMemoryModel: Executions I find profoundly troubling

From: Jerry Schwarz (jerry.schwarz@oracle.com)
Date: Mon Jul 28 2003 - 13:11:19 EDT


At 08:24 AM 7/28/2003, Bill Pugh wrote:
>At 2:50 AM -0700 7/28/03, Jerry Schwarz wrote:
>>
>>That result can arise quite naturally if the compiler transforms Thread 2 to
>>
>> r1=x
>> y=x
>
>Sorry, not legal. One of the key limitations on compilers in a
>multithreaded context is that they cannot introduce additional redundant
>reads of shared variables, unless it guarantees that the reads will return
>the same value. A read of a shared variable into a local variable needs to
>be considered an atomic action with just one value stored into the local.

In my view, if the programmer wants to impose that constraint then they
need to declare the shared variable (i.e. the field) volatile.

Put another way. If the code doesn't contain any threading constructs
(volatile, synchronize, ...) then the compiler shouldn't be forced to treat
the code is if it will be running in a multithreaded context.

>Consider:
>Initially, a = null
>
>Thread 1:
>a = "Hello"
>
>Thread 2:
>r1 = a
>if (r1 != null)
> r2 = r1.hashCode();
>
>The compiler must not be allowed to transform the code for thread 2 to:
>
>Thread 2:
>if (a != null)
> r2 = a.hashCode();
>
>In this code, you can get a null pointer execution that isn't possible in
>the original code.
>
>
>>
>>What do we say to disallow this outcome? Do you want to disallow
>>redundant loads? That is a pretty severe constraint on compilers?
>
>Neither Sarita's model nor mine (nor the original JMM) allows this
>transformation. Loading a shared variable into a local variable should
>guarantee that the local variable has exactly one value that cannot be
>changed by other threads.
>
>
>>
>>>Example 2:
>>>Initially, x = 0, y = 0, a[0] = 1, a[1] = 2
>>>
>>> Thread 1 Thread 2
>>> r1 = X r3 = Y
>>> a[r1] = 0 X = r3
>>> r2 = a[0]
>>> Y = r2
>>>
>>>Troubling execution r1 == r2 == r3 == 1
>>>
>>>This execution is troubling because in order for r2 to be 1, r1 must
>>>have been 1. But r1 could be one only if thread 2 wrote 1 to X. Which
>>>could only be true if thread 2 read 1 from Y. Which could only be true
>>>if r2 is 1.
>>
>>
>>Transform Thread 1 to
>>
>> Y=a[0]
>> r1 = X
>> a[r1] = 0
>> r2 = a[0]
>> if ( X == 0 ) Y = 0
>
>Sorry, but you can't speculatively perform a write, and then later write a
>different corrective value if you determine that the value written
>speculatively was incorrect. Neither Sarita's model, my model, nor the
>original JMM allow this transformation. Consider:
>
>Initially: x = 0, y = 0
>
>thread 1:
>r1 = x
>y = r1
>
>Thread 2:
>r2 = y
>
>It would be insanely bad to allow the transformation of thread 1 to:
>
>thread 1:
>y = 42
>r1 = x
>if r1 != 42
> y = r1
>
>In addition to the problem with speculative writes, the transformed code
>has also duplicated reads.
>
>
>

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



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