I've read from this article that:
...Synchronized blocks also guarantee that all variables accessed inside the synchronized block will be read in from main memory, and when the thread exits the synchronized block, all updated variables will be flushed back to main memory again, regardless of whether the variable is declared
volatileor not.
There's also an example showed in Effective Java:
public class StopThread {
private static boolean stopRequested;
private static synchronized void requestStop() {
stopRequested = true;
}
private static synchronized boolean stopRequested() {
return stopRequested;
}
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(() -> {
int i = 0;
while (!stopRequested()) i++
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
requestStop();
}
}
The variable stopRequested is not declared as volatile and the author states that "...In other words, the synchronization on these methods is used solely for its communication effects, not for mutual exclusion...". But I would like to know that, in case of accessing an element of an array or accessing a field of an object in a synchronized method/block, could we always guarantee the memory visibility, without having to manually force a volatile access of the array's element (by using Unsafe#getObjectVolatile for example) or declare the volatile modifier on the object's field? Thanks!
// flags is an instance of a custom class. Should Flags.stopRequested be declared volatile?
public class StopThread {
private static Flags flags = new Flags();
private static synchronized void requestStop() {
flags.stopRequested = true;
}
private static synchronized boolean stopRequested() {
return flags.stopRequested;
}
}
// flags is an array. Should we use getObjectVolatile/putObjectVolatile to access the element?
public class StopThread {
private static boolean[] flags = new boolean[n];
private static synchronized void requestStop() {
flags[m] = true;
}
private static synchronized boolean stopRequested() {
return flags[m];
}
}