[concurrency-interest] Synchronization of data read by multiple threads

Ryan LeCompte ryan.lecompte at pangonetworks.com
Tue Oct 25 11:25:36 EDT 2005


I'm a bit unclear with your first answer regarding a non-primitive field.
What exactly do you mean by "invariant" here? I was thinking of a
non-primitive field, such as (String foo;) that could be read/modified by
multiple threads. If the program required that whenever the variable "foo"
is used in method1, method2, or method3 that it's most recently written
value is always returned, then method1/method2/method3 would have to be
synchronized (on the same lock of course) OR the 'foo' variable would have
to be declared volatile. 

Ryan

-----Original Message-----
From: Jeremy Manson [mailto:jmanson at cs.purdue.edu] 
Sent: Tuesday, October 25, 2005 11:17 AM
To: Ryan LeCompte
Cc: concurrency-interest at altair.cs.oswego.edu
Subject: Re: [concurrency-interest] Synchronization of data read by multiple
threads

Ryan LeCompte wrote:
> Thanks for the response, Jeremy. I believe I definitely have a handle on
> this now. The idiom that I've described would also be necessary for
> non-primitives, right? 

If the field being accessed were part of some invariant that required 
mutual exclusion / atomicity guarantees for multiple fields, then yes.

> Also, in practice, how "common" is it that one sees
> odd behavior in their programs when they don't properly follow the idiom
> that I've described here (synchronization or volatile approach)? I believe
> Josh Bloch mentions in his book "Effective Java" that you may only see bad
> side effects if you're on a multi processor machine.

You can see lots of nasty things on a uniprocessor.  The compiler can 
perform transformations that cause results on a uniprocessor that are 
just as surprising as any results on a multiprocessor.  YMMV, of course, 
depending on the program, the compiler, and the architecture.

For example, consider the following:

boolean stopped = false;

Thread 1:
while (!stopped) {
   // do stuff not affecting stopped
}

Thread 2:
stopped = true;

It would be perfectly legal for a compiler to examine the code in Thread 
1 and determine that it does not change the value of stopped.  It could 
then decide that what you have in Thread 1 is an infinite loop, and 
remove the loop guard:

Replacement Thread 1:
if (!stopped) {
   while (true) {
     // do stuff
   }
}

And Thread 1 will never end, regardless of what Thread 2 does.

On the other hand, if you declare stopped to be volatile, you are 
telling the compiler it can be modified by another thread.  It then 
won't perform this transformation.

					Jeremy



More information about the Concurrency-interest mailing list