If we declare, the counter variable : volatile, all writes to the counter variable will be written back to main memory, immediately
All reads of the counter variable will be read directly from main memory.
Declaring the counter variable “volatile” is enough to guarantee visibility for T2 of writes to the counter variable
If both T1 and T2 tries to increment the counter variable, then declaring the counter variable volatile would not be enough to ensure that the 2nd thread sees the latest written value
The short time gap in between the reading of the volatile variable and the writing of its new value will create a race condition.
Then multiple threads might read the same value of the volatile variable, generate a new value for the variable and when write the value back to main memory will overwrite each other's values.
In this case we need to use synchronized
It guarantees that the reading and writing of the variable is atomic
Reading or writing a volatile variable does not block threads reading or writing
So we must use the synchronized keyword around critical sections
If Thread A writes to a volatile variable and Thread B reads the same volatile variable, then all variables visible to Thread A before writing the volatile variable, will also be visible to Thread B after it has read the volatile variable.
If Thread A reads a volatile variable, then all all variables visible to Thread A when reading the volatile variable will also be re-read from main memory.
The Java VM and the CPU are allowed to reorder instructions in the program for performance reasons, as long as the semantic meaning of the instructions remain the same
Consider :
int a = 1; int b = 2; a++; b++;
These instructions can be reordered, without changing the semantic meaning to :
int a = 1; a++; int b = 2; b++;
public class MyClass {
private int years;
private int months
private volatile int days;
public void update(int years, int months, int days){
this.years = years;
this.months = months;
this.days = days;
}
}
But, what if the Java VM reordered the instructions, like this:
public void update(int years, int months, int days){
this.days = days;
this.months = months;
this.years = years;
}
The happens-before guarantee guarantees that:
The reads or writes before a write to a volatile variable are guaranteed to "happen before" the write to the volatile variable
All reads from and writes to other variables cannot be reordered to occur before a read of a volatile variable if reads or writes originally occurred after the read of the volatile variable