Java / volatile
volatile keyword indicates that a variable's value will be modified by different threads.
When a java variable is declared volatile,
- The value of that varilable will not be cached thread-locally, all read/write will be directed to the "main memory".
- Access to the variable is synchronized on itself.
synchronized | volatile |
Synchronized block applies only to object. | volatile keyword can be applied to Object or primitive types. |
Synchronized block does not work on null. Attempting to synchronize on a null object will throw a NullPointerException. | volatile variables can be null. |
synchronized blocks other threads while one thread is accessing the block. | volatile does not block any threads. |
synchronization occurs when you enter a synchronized block. | synchronization occurs when a volatile variable is accessed. |
Yes, however the volatility is limited to the reference pointing to an array and not the whole array or individual array elements.
long/double are 64-bit wide and it is read first 32 bit and next other 32 bits, so it is non-atomic.
yes, reading/writing a volatile long/double variable is atomic.
- enable reading/writing into double/long as atomic.
- volatile variable enables Java memory model to have memory barrier so that when write is performed on a volatile variable it is guaranteed that any thread accessing that thread will see the value written.
Since Java 5 the volatile keyword guarantees more than just the reading from and writing to main memory of variables.
If Thread A writes to a volatile variable and Thread B subsequently 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.
Developers may use this extended visibility guarantee to optimize the visibility of variables between threads. Instead of declaring each and every variable volatile, only one or a few need be declared volatile.
Thread A:
sharedObject.myNonVolatileVar = 123; sharedObject.myVolatileVar = sharedObject.myVolatileVar + 1;
Thread B:
int myVolatileVar = sharedObject.myVolatileVar; int myNonVolatileVar = sharedObject.myNonVolatileVar;
package com.tutorials.volatileKeyword.volatileExample; public class MyThread { private static volatile int Shared_Variable = 0; public static void main(String[] args) { new ReadOnChange().start(); new Writer().start(); } static class ReadOnChange extends Thread { @Override public void run() { int local_value = Shared_Variable; while (local_value < 5) { if (local_value != Shared_Variable) { System.out.println("Value changed for Shared_Variable :" + Shared_Variable); local_value = Shared_Variable; } } } } static class Writer extends Thread { @Override public void run() { int local_value = Shared_Variable; while (Shared_Variable < 5) { System.out.println("changing the Shared_Variable to " + (local_value + 1)); Shared_Variable = ++local_value; try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
Output:
changing the Shared_Variable to 1 Value changed for Shared_Variable :1 changing the Shared_Variable to 2 Value changed for Shared_Variable :2 changing the Shared_Variable to 3 Value changed for Shared_Variable :3 changing the Shared_Variable to 4 Value changed for Shared_Variable :4 changing the Shared_Variable to 5 Value changed for Shared_Variable :5
Output (with no volatile keyword):
changing the Shared_Variable to 1 changing the Shared_Variable to 2 changing the Shared_Variable to 3 changing the Shared_Variable to 4 changing the Shared_Variable to 5
Yes. A primitive variable can be volatile as well as objects.
Locking guarantee both visibility and atomicity while volatile variable can guarantee only the visibility.
Volatile variable means it is shared so the operations on it should not be reordered with other memory operations.
These variables are not to be cached in registers or in other caches so that a read on volatile Caroline always fetch the most recent write by any thread.
No. Java does not allow that because final variable value cannot be changed once initialized.