I'm trying to learn the terminologies used in multi-threading in Java. So please correct me if I used wrong definition in following text:
My findings from different resources
Atomic action: According to Java doc:
In programming, an atomic action is one that effectively happens all at once. An atomic action cannot stop in the middle: it either happens completely, or it doesn't happen at all. No side effects of an atomic action are visible until the action is complete.
And that's why reading or writing to long or double variables are not atomic. Because it involves two operations, first 32-bit and the second-32 bit read/write to the variable. Also, from the paragraph above, I understand that if I used synchronized
on a method, it will make the method atomic (theoretically speaking).
Volatile variables: Also from Java Doc:
This means that changes to a volatile variable are always visible to other threads. What's more, it also means that when a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change.
Now, also according to Effective Java 2nd Edition by Joshua Bloch, consider the following points mentioned in the book about volatile
declaration:
Consider the following:
// Broken - requires synchronization!
private static volatile int nextSerialNumber = 0;
public static int generateSerialNumber() {
return nextSerialNumber++;
}
The method’s state consists of a single atomically accessible field, nextSerialNumber, and all possible values of this field are legal. Therefore, no synchronization is necessary to protect its invariants. Still, the method won’t work properly without synchronization.
This is because nextSerialNumber++
is not atomic as it performs read, increment, write.
My summary
So if nextSerialNumber++
is not atomic, and requires synchronize
. Then why the following is atomic and doesn't require synchronize?
private static volatile long someNumber = 0;
public static int setNumber(long someNumber) {
return this.someNumber = someNumber;
}
What I don't understand is why using volatile on double
or long
, makes it atomic?
Because all volatile
does is that it makes sure if thread B tried to read a long
variable that is being written by thread A, and only 32-bit of it is written by thread A, then when thread B accesses the resource, it would get the 32-bit number that was written by thread A. And that doesn't make it atomic as the definition of the term atomic is explained in Java Doc.