Java concurrency - why doesn't setter synchronization (but not getter) make the class thread safe?

Possible duplicate:
Thread Safety in Java Class

I read Java concurrency in practice, and I came up with an example that puzzles me.

The authors claim that this class is not thread safe.

public class MutableInteger { private int number; public int getInt() { return number; } public void setInt(int val) { number = val; } } 

And they also state that only one method (e.g. setter) will not be synchronized; You must sync both.

My question is why? Wouldn't setter sync only?

+6
java shared-memory concurrency thread-safety
source share
4 answers

Java takes place before / after the memory model. There must be some kind of general parallel construction (e.g., a synchronized block / method, lock, volatile, atomic) both in the write path and in the read path in order to cause this behavior.

If you synchronize both methods, you create a lock for the entire object that will be used by both read and write streams. The JVM ensures that any changes that occur in the write stream that occur before exiting the (synchronized) setInt method are visible to any read streams after they enter the (synchronized) getInt method. The JVM will introduce the necessary memory barriers for this to happen.

If only the write method is synchronized, changes to the object may not be visible to any read stream. This is because the read path that the JVM can use to make sure that the visible memory of the read stream (cache, etc.) matches the write stream does not exist. Make sure the getInt method is synchronized.

Note: in this case, changing the volatility of the "number" of the field will give the correct behavior, since volatile read / write also provides the same behavior of memory visibility in the JVM, and the action inside the setInt method is just the destination.

+5
source share

This is explained in the book before the sample (p. 35):

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

Obsolete data: when the reader stream is ready, it may see an obsolete value. If synchronization is not used every time the variable is accessed, you can see the outdated value for this variable. Worse, stalinism is not all or nothing: a thread can see the updated value of one variable, but the obsolete value of another variable that was written first.

+5
source share

If you only synchronize the setter method, you can guarantee that the attribute will not be changed incorrectly, but you cannot be sure that it is an obsolete value when you try to read the variable.

+1
source share

because number unstable, and getInt() not synchronized, getInt() can return obsolete values. Read about the Java memory model for more information.

-one
source share

All Articles