[concurrency-interest] concurrency puzzle

Jeremy Manson jmanson at cs.umd.edu
Sun Sep 10 12:07:20 EDT 2006


I'm not sure what you mean by multithreaded environment, because all 
Java code runs in a multithreaded environment.  If the object is 
constructed and foo() runs in a single thread, this program will print 
20.  This is because the write to 20 is the last write to x that 
happens-before the print.  If another thread sneaks in a write to x, 
then it might print something else, but there is no other thread in this 
example.

If, on the other hand, you are worried about the case where one thread 
constructs the object and passes it to another thread via a data race:

Thread 1:
global.a = new A();

Thread 2:
if (global.a != null)
   global.a.foo();

Then it will either print 20 or 10.  It can't print 0 because the write 
of the default value (conceptually) happens-before the first action of 
every thread.  This means that Thread 2's write of 20 to x will 
overwrite the value of 0.

This can be avoided by making global.a volatile, although you still 
might get a NullPointerException in Thread 2.

I'm not sure which JMM documentation you have been examining, if it 
talks about local memory and invalidation.  The old one had kind-of a 
notion of local memory, but it hasn't been the "active" JMM for a good 
while.  Certainly, that JMM didn't talk about safe publication.

And speaking of safe publication - the write of 10 to x happens in the 
constructor, according to the semantics of the Java programming 
language.  If it were a final field (which is where the notion of safe 
publication is important), then it would be considered to be published 
safely, unless a reference to the object escapes an otherwise-unseen 
constructor.

Now, a /different/ thread could see 0 or 10 or 20 for x:

Thread 1:
global.a = new A();
global.a.foo();

Thread 2:
r1 = global.a.x;

r1 can be 0, 10 or 20

It can avoid this by synchronizing properly.

					Jeremy

Peter Veentjer wrote:
> I'm playing with the Java Memory Model documentation. And to check if
> my understanding is correct, I'm interested in the following example:
> 
> public class A{
>    private int x = 10;
> 
>    public void foo(){
>       x = 20;
>       synchronized(this){
>          System.out.println( x );
>       }
>    }
> }
> 
> If this class is used in a multithreaded environment, what could the
> output be? (foo is called only once to make it easy)
> 
> 20: if the x=20 is written to main memory, the read for println( x )
> will return 20.
> 
> 10: if x=20 isn't written to main memory, but only in local memory,
> the write (x=20) could get lost. This is because the local memory is
> invalidated when the lock on this is acquired. When x is read for the
> println, it will return the value in main memory (and that is 10).
> 
> 0: the 10 value doesn't need to be visible in main memory because it
> isn't published safely. So for the same reasons 10 could be read for
> the println, the default value for int (that is a 0) could be read for
> the println.
> 
> 0: a different thread could obtain a partially initialized reference
> to A because of reordening. So 0 could be the value of x when it is
> read for the println statement. So this is another way the 0 value
> could be found.
> 
> So my bet would be
> 
> 20 or 10 or 0.
> 
> Is my understanding correct?
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at altair.cs.oswego.edu
> http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest



More information about the Concurrency-interest mailing list