@ThreadSafe
public class SynchronizedInteger {
@GuardedBy("this") private int value;
public synchronized int get() { return value; }
public synchronized void set(int value) { this.value = value; }
}
The book says:
A good way to think about volatile variables is to imagine that they behave roughly like the SynchronizedInteger class
in Listing 3.3, replacing reads and writes of the volatile variable with calls to get and set.
…
This analogy is not exact; the memory visibility effects of SynchronizedInteger are actually slightly stronger than those of volatile variables. See
Chapter 16.
I checked chapter 16, but didn’t find an exact answer – how exactly the memory visibility guarantees are stronger?
The main difference is that
volatilecreates a happens-before relationship between a write to thevolatilevariable and a subsequest read from it, whereassynchronizedcreates happens-before relationships between an unlock and a subsequent lock.So, in the case of
SynchronizedIntegerhappens-before relationship is created between any consequent operations withSychrozniedInteger(i.e.get()andset()calls), and it doesn’t matter whether they are reads or writes. It differs from the behaviour ofvolatile intthat provide happens-before only between a write and a consequent read.Actually I can’t imagine any meaningful example to illustrate this difference, so that these behaviours really differ only slightly.