First note that ++
on a volatile
variable is not atomic, hence, you can’t rely on its value in case of multiple updates.
As long as there is only a single update, it may be sufficient to check whether the update did happen, but it is crucial to perform the check. Otherwise, there is no guaranty that the (supposed to be acquire) volatile read is subsequent to the (supposed to be release) volatile update.
Just consider the following timing:
Thread 1 Thread 2
┌ ┐ [ Read I ]
│ map update │ ┌ ┐
└ ┘ │ map query │
[ Write I ] └ ┘
Here, the two threads use the map concurrently, which is hopelessly broken, while the acquire and release actions have no consequences, as the acquire is not subsequent to the release.
You can only rely on this relationship if you check the value you’ve read and proceed only when it is the expected value written by the other thread.
Since the whole construct would work only for a single update, you can use a boolean
instead:
private static volatile boolean I = false;
private static final Map<String, String> MAP = new HashMap<>();
// run at Thread-1
public static void write(){
MAP.put("test", "test");
I = true; // release
}
// run at Thead-2
public static void read(){
if(I) { // acquire
MAP.get("test"); // want to see the modifying by write()
}
}
You can not use this for more than one update, as the thread wanting to perform a second update must ensure not to start updating the map before all threads reading the map after the first update have completed. But this information is not available at all with this approach.
ConcurrentHashMap
and remove the wholevolatile int I
? – Endoravolatile
variables are never cached by a thread. But that doesn't mean that the access toMAP
is thensynchronize
d across all threads. You'd have to do that yourselves – Endorahappends-before order
sayIf x and y are actions of the same thread and x comes before y in program order, then hb(x, y).
andIf an action x synchronizes-with a following action y, then we also have hb(x, y).
, theI++
is synchronized withint i = I;
, andIf hb(x, y) and hb(y, z), then hb(x, z).
. – Elemental