I\'m reading about volatile keyword in Java and completely understand the theory part of it.
But, what I\'m searching for is, a good case example, which sho
Variable Volatile: Volatile Keyword is applicable to variables. volatile keyword in Java guarantees that value of the volatile variable will always be read from main memory and not from Thread's local cache.
Access_Modifier volatile DataType Variable_Name;
Volatile Field: An indication to the VM that multiple threads may try to access/update the field's value at the same time. To a special kind of instance variables which has to shared among all the threads with Modified value. Similar to Static(Class) variable, Only one copy of volatile value is cached in main memory, So that before doing any ALU Operations each thread has to read the updated value from Main memory after ALU operation it has to write to main memory direclty. (A write to a volatile variable v synchronizes-with all subsequent reads of v by any thread) This means that changes to a volatile variable are always visible to other threads.
Here to a nonvoltaile variable
if Thread t1 changes the value in t1's cache, Thread t2 can't access the changed value untill t1 writes, t2 read from main memory for the most recent modified value, which may lead to Data-Inconsistancy
.
volatile cannot be cached - assembler
+--------------+--------+-------------------------------------+ | Flag Name | Value | Interpretation | +--------------+--------+-------------------------------------+ | ACC_VOLATILE | 0x0040 | Declared volatile; cannot be cached.| +--------------+--------+-------------------------------------+ |ACC_TRANSIENT | 0x0080 | Declared transient; not written or | | | | read by a persistent object manager.| +--------------+--------+-------------------------------------+
Shared Variables: Memory that can be shared between threads is called shared memory or heap memory. All instance fields, static fields, and array elements are stored in heap memory.
Synchronization: synchronized is applicable to methods, blocks. allows to execute only 1-thread at a time on object. If t1 takes control, then remaining threads has to wait untill it release the control.
Example:
public class VolatileTest implements Runnable {
private static final int MegaBytes = 10241024;
private static final Object counterLock = new Object();
private static int counter = 0;
private static volatile int counter1 = 0;
private volatile int counter2 = 0;
private int counter3 = 0;
@Override
public void run() {
for (int i = 0; i < 5; i++) {
concurrentMethodWrong();
}
}
void addInstanceVolatile() {
synchronized (counterLock) {
counter2 = counter2 + 1;
System.out.println( Thread.currentThread().getName() +"\t\t « InstanceVolatile :: "+ counter2);
}
}
public void concurrentMethodWrong() {
counter = counter + 1;
System.out.println( Thread.currentThread().getName() +" « Static :: "+ counter);
sleepThread( 1/4 );
counter1 = counter1 + 1;
System.out.println( Thread.currentThread().getName() +"\t « StaticVolatile :: "+ counter1);
sleepThread( 1/4 );
addInstanceVolatile();
sleepThread( 1/4 );
counter3 = counter3 + 1;
sleepThread( 1/4 );
System.out.println( Thread.currentThread().getName() +"\t\t\t\t\t « Instance :: "+ counter3);
}
public static void main(String[] args) throws InterruptedException {
Runtime runtime = Runtime.getRuntime();
int availableProcessors = runtime.availableProcessors();
System.out.println("availableProcessors :: "+availableProcessors);
System.out.println("MAX JVM will attempt to use : "+ runtime.maxMemory() / MegaBytes );
System.out.println("JVM totalMemory also equals to initial heap size of JVM : "+ runtime.totalMemory() / MegaBytes );
System.out.println("Returns the amount of free memory in the JVM : "+ untime.freeMemory() / MegaBytes );
System.out.println(" ===== ----- ===== ");
VolatileTest volatileTest = new VolatileTest();
Thread t1 = new Thread( volatileTest );
t1.start();
Thread t2 = new Thread( volatileTest );
t2.start();
Thread t3 = new Thread( volatileTest );
t3.start();
Thread t4 = new Thread( volatileTest );
t4.start();
Thread.sleep( 10 );;
Thread optimizeation = new Thread() {
@Override public void run() {
System.out.println("Thread Start.");
Integer appendingVal = volatileTest.counter2 + volatileTest.counter2 + volatileTest.counter2;
System.out.println("End of Thread." + appendingVal);
}
};
optimizeation.start();
}
public void sleepThread( long sec ) {
try {
Thread.sleep( sec * 1000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Static[
Class Field
] vs Volatile[Instance Field
] - Both are not cached by threads
Static fields are common to all threads and get stored in Method Area. Static with volatile no use. Static field cant be serialized.
Volatile mainly used with instance variable which get stored in heap area. The main use of volatile is to maintain updated value over all the Threads. instance volatile field can be Serialized.
@see
Ideally, if keepRunning wasn't volatile, thread should keep on running indefinitely. But, it does stop after few seconds.
If you are running in a single-processor or if your system is very busy, the OS may be swapping out the threads which causes some levels of cache invalidation. Not having a volatile
doesn't mean that memory will not be shared, but the JVM is trying to not synchronize memory if it can for performance reasons so the memory may not be updated.
Another thing to note is that System.out.println(...)
is synchronized because the underlying PrintStream
does synchronization to stop overlapping output. So you are getting memory synchronization "for free" in the main-thread. This still doesn't explain why the reading loop sees the updates at all however.
Whether the println(...)
lines are in or out, your program spins for me under Java6 on a MacBook Pro with an Intel i7.
Can anyone explain volatile with example ? Not with theory from JLS.
I think your example is good. Not sure why it isn't working with all System.out.println(...)
statements removed. It works for me.
Is volatile substitute for synchronization ? Does it achieve atomicity ?
In terms of memory synchronization, volatile
throws up the same memory barriers as a synchronized
block except that the volatile
barrier is uni-directional versus bi-directional. volatile
reads throw up a load-barrier while writes throw up a store-barrier. A synchronized
block is a bi-directional barrier with the addition of mutex locking.
In terms of atomicity
, however, the answer is "it depends". If you are reading or writing a value from a field then volatile
provides proper atomicity. However, incrementing a volatile
field suffers from the limitation that ++
is actually 3 operations: read, increment, write. In that case or more complex mutex cases, a full synchronized
block may be necessary. AtomicInteger
solves the ++
issue with a complicated test-and-set spin-loop.
Please find the solution below,
The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory". The volatile force the thread to update the original variable for each time.
public class VolatileDemo {
private static volatile int MY_INT = 0;
public static void main(String[] args) {
ChangeMaker changeMaker = new ChangeMaker();
changeMaker.start();
ChangeListener changeListener = new ChangeListener();
changeListener.start();
}
static class ChangeMaker extends Thread {
@Override
public void run() {
while (MY_INT < 5){
System.out.println("Incrementing MY_INT "+ ++MY_INT);
try{
Thread.sleep(1000);
}catch(InterruptedException exception) {
exception.printStackTrace();
}
}
}
}
static class ChangeListener extends Thread {
int local_value = MY_INT;
@Override
public void run() {
while ( MY_INT < 5){
if( local_value!= MY_INT){
System.out.println("Got Change for MY_INT "+ MY_INT);
local_value = MY_INT;
}
}
}
}
}
Please refer this link http://java.dzone.com/articles/java-volatile-keyword-0 to get more clarity in it.
Volatile --> Guarantees visibility and NOT atomicity
Synchronization (Locking) --> Guarantees visibility and atomicity (if done properly)
Volatile is not a substitute for synchronization
Use volatile only when you are updating the reference and not performing some other operations on it.
Example:
volatile int i = 0;
public void incrementI(){
i++;
}
will not be thread safe without use of synchronization or AtomicInteger as incrementing is an compound operation.
Why program does not run indefinitely?
Well that depends on various circumstances. In most cases JVM is smart enough to flush the contents.
Correct use of volatile discusses various possible uses of volatile. Using volatile correctly is tricky, I would say "When in doubt, Leave it out", use synchronized block instead.
Also:
synchronized block can be used in place of volatile but the inverse is not true.
Lot's of great examples, but I just want to add that there are a number of scenarios where volatile
is required so there is no one concrete example to rule them a.
volatile
to force all threads to get latest value of the variable from main memory.synchronization
to guard critical dataLock
APIAtomic
variablesCheck it out for more Java volatile examples.
I have modified your example slightly. Now use the example with keepRunning as volatile and non volatile member :
class TestVolatile extends Thread{
//volatile
boolean keepRunning = true;
public void run() {
long count=0;
while (keepRunning) {
count++;
}
System.out.println("Thread terminated." + count);
}
public static void main(String[] args) throws InterruptedException {
TestVolatile t = new TestVolatile();
t.start();
Thread.sleep(1000);
System.out.println("after sleeping in main");
t.keepRunning = false;
t.join();
System.out.println("keepRunning set to " + t.keepRunning);
}
}