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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…