Volatile
The volatile modifier is used to let the JVM know that a thread accessing the variable must always merge its own private copy of the variable with the master copy in the memory. Accessing a volatile variable synchronizes all the cached copies of the variables in the main memory.
- volatile is a modifier applicable only for variables and we can't apply it anywhere else.
- if the value of a variable keeps on changing by multiple threads then there may be a chance of a data inconsistency problem we can solve this problem by using a volatile modifier.
- if a variable declares as volatile then for every thread jvm will create a separate local copy every modification performed by the thread will take place in a local copy there is no effect on the remaining threads.
Advantage of volatile keyword-:
the main advantage of volatile keyword is we can overcome data inconsistency problems.
Disadvantage of volatile keyword-:
the main disadvantage volatile keyword is creating and maintaining a separate copy for every thread increases the complexity of programming and creates performance problems hence if there no specific requirement it is never recommended to use the volatile keyword and it is the almost deprecated keyword.
Note-: final variable means the value never changes whereas volatile variables mean keep on changing hence volatile final is an illegal combination for variables.
eg-:
public class MyRunnable implements Runnable{
private volatile boolean avtive;
public void run(){
active=true;
while(active){
}
}
public void stop(){
active=false;
}
}
Memory Visibility
In this simple example, we have two application threads: the main thread and the reader thread. Let's imagine a scenario in which the OS schedules those threads on two different CPU cores, where:
- The main thread has its copy of ready and number variables in its core cache.
- The reader thread ends up with its copies, too.
- The main thread updates the cached values.
On most modern processors, write requests won't be applied right after they're issued. In fact, processors tend to queue those writes in a special write buffer. After a while, they'll apply those writes to the main memory all at once.
With all that being said, when the main thread updates the number and ready variables, there's no guarantee about what the reader thread may see. In other words, the reader thread may see the updated value right away, with some delay, or never at all.
This memory visibility may cause liveness issues in programs relying on visibility.
volatile and Thread Synchronization
- Mutual Exclusion – only one thread executes a critical section at a time
- Visibility – changes made by one thread to the shared data are visible to other threads to maintain data consistency
synchronized methods and blocks provide both of the above properties at the cost of application performance.
volatile is quite a useful keyword because it can help ensure the visibility aspect of the data change without providing mutual exclusion. Thus, it's useful in the places where we're ok with multiple threads executing a block of code in parallel, but we need to ensure the visibility property.