in Java Performance Tuning by Jack Shirazi it writes:
This means that access and update of variables are automatically synchronized (as long as they are not longs or doubles). If a method consists solely of a variable access or assignment, there is no need to make it synchronized for thread safety, and every reason not to do so for performance. Thread safety extends further to any set of statements that are accessing or assigning to a variable independently of any other variable values.
according to the description above, operations like flag = true
is always atomic and does not need synchronize
.
However, here comes another article that regards the flollowing circumstance as data race:
class DataRaceExample {
static boolean flag = false;//w0
static void raiseFlag() {
flag = true;//w1
}
public static void main(String... args) {
ForkJoinPool.commonPool().execute(DataRaceExample::raiseFlag);
while (!flag);//r_i, where i ∈ [1, k), k may be infinite
System.out.print(flag);//r
}
}
and the author says:
Now, all executions have data races, because the flag is not volatile
It confused me a lot for the conflits between the two articles.
The point that Jack Shirazi is trying to make is that non-volatile accesses to primitive types other than double
and long
are guaranteed to be performed atomically according to the JMM. Thus, synchronization is unnecessary to prevent, for example, torn reads and writes in the presence of concurrent accesses.
The confusion arises because his book predates JSR-133 and he uses terms like "automatically synchronized" which is not in line with modern notions of synchronization within the JMM.