views:

147

answers:

4

Possible Duplicate:
Thread safety in Java class

I'm reading Java concurrency in Practice (good book so far), and I've come to an example that puzzles me.

The authors state that this class is not threadsafe

public class MutableInteger{

  private int number;

  public int getInt(){return number;}

  public void setInt(int val){number = val;}
}

And that syncronizing only one method (the setter for example) would not do. You have to syncronize both.

My question is Why? Wouldn't syncronizing the setter just do?

Thanks a lot

+2  A: 

Java has a happens before/happens after memory model. There needs to be some common concurrent construct (e.g. synchronized block/method, lock, volatile, atomic) on both the write path and the read path to trigger this behaviour.

If you synchronize both methods you are creating a lock on the whole object that will be shared by both the read and write threads. The JVM will ensure that any changes that occur on the writing thread that occur before leaving the (synchronized) setInt method will be visible to any reading threads after they enter the (synchronized) getInt method. The JVM will insert the necessary memory barriers/cache flushes to ensure that this will happen.

If only the write method is synchronized then changes to the object may not be visible to any reading thread. This is because there is no point on the read path that the JVM can use to ensure that the reading thread's visible memory (cache's etc.) are in line with the writing thread. Make the getInt method synchronized would provide that.

Note: specifically in this case making the field 'number' volatile would give the correct behaviour as volatile read/write also provides the same memory visibility behaviour in the JVM and the action inside of the setInt method is only an assignment.

Michael Barker
This is a typical comment line.
Andreas_D
A: 

because number is not volatile, and getInt() is not synchronized, getInt() may return stale values. For more information, read about the java memory model.

Bwmat
Sorry, the answer is at least incomplete and the hint useless to my eyes. He asked for an explanation on a concrete problem (-1)
Andreas_D
+5  A: 

It's explained in the book before the sample (page 35):

"Synchronizing only the setter would not be sufficient: threads calling get would still be able to see stale values."

Stale data: When the reader thread examines ready, it may see an out-of-date value. Unless synchronization is used every time a variable is accessed, it is possible to see a stale value for that variable. Worse, staleness is not all-or-nothing: a thread can see an up-to-date value of one variable but a stale value of another variable that was written first.

Soundlink
**I am** reading the book, saying that "it will be able to see stale values" is not enough, I want fundaments.
Pablo Fernandez
So, you are not believing, that there it the possibility to see stale value if the getter is not synchronized and you want a prove for it, or what do you mean?
Soundlink
I want to understand why. The reason is that threads keep local cached values of the variables, and the reads might not flush the cache. If the cache wasn't there, it wouldn't matter if there were synchronized methods or not (both operations are atomic)
Pablo Fernandez
+1  A: 

If you only Synchronize the setter method, you could only guarantee the attribute would not be amended incorrectly, but you could not be sure it is stale value when you try to read the variable.

Wei S