Any way Volatile keyword in Java is used as an indicator to Java compiler and Thread that do not cache value of this variable and always read it from main memory. So if you want to share any variable in which read and write operation is atomic by implementation e.g. read and write in int or boolean variable you can declare them as volatile variable. From Java 5 along with major changes like Autoboxing, Enum, Genericsand Variable arguments , Java introduces some change in Java Memory Model (JMM), Which guarantees visibility of changes made by one thread to another also as "happens-before" which solves the problem of memory writes that happen in one thread can "leak through" and be seen by another thread. Java volatile keyword cannot be used with method or class and it can only be used with variable. Java volatilekeyword also guarantees visibility and ordering , after Java 5 write to any volatile variable happens before any read into volatile variable. By the way use of volatile keyword also prevents compiler or JVM from reordering of code or moving away them from synchronization barrier.
On the previous pages, we've looked at the definition of volatile and seen some of the additional atomic access to volatile variables provided by Java 5. We've also seen that volatile variables share some features (in particular the memory synchronization behaviour) of synchronized access to an object. So when should you use volatile?
First, the easy cases where you basically don't need volatile or any other synchronization mechanism:
volatile is not necessary– or in fact possible– for fields that are immutable (declared final);
volatile is not necessary for variables that are accessed by only one thread (though of course you have to make a correct decision that they are only accessed by one thread!);
volatile is not suitable for complex operations where you need to prevent access to a variable for the duration of the operation: in such cases, you should use object synchronization or one of Java 5's explicit lock classes added.
Now some typical uses.
A "simple flag" accessed by multiple threads
The most typical case is where: you write a variable, such as a flag, in one thread; you check that variable in another thread; crucially, the value to write doesn't depend on the current value......or, you don't care about "missing an update". We looked at the example of a volatile flag to control a loop.
So what happens? Each thread has its own stack, and so its own copy of variables it can access. When the thread is created, it copies the value of all accessible variables in its own memory. The volatile keyword is used to say to the jvm "Warning, this variable may be modified in an other Thread". Without this keyword the JVM is free to make some optimizations, like never refreshing those local copies in some threads. The volatile force the thread to update the original variable for each variable. The volatile keyword could be used on every kind of variable, either primitive or objects! Maybe the subject of another article, more detailed with example.
Example:
package com.string;
import java.util.logging.Level;
import java.util.logging.Logger;
public class VolatileTest {
private static final Logger LOGGER = Logger.getLogger("VolatileTest.class");
private static volatile int MY_INT = 0;
public static void main(String[] args) {
new ChangeMaker().start();
new ChangeListener().start();
}
static class ChangeListener extends Thread {
@Override
public void run() {
int local_value = MY_INT;
while (local_value < 5) {
if (local_value != MY_INT) {
LOGGER.log(Level.INFO, "Got Change for MY_INT : {0}",
MY_INT);
local_value = MY_INT;
}
}
}
}
static class ChangeMaker extends Thread {
@Override
public void run() {
int local_value = MY_INT;
while (MY_INT < 5) {
LOGGER.log(Level.INFO, "Incrementing MY_INT to {0}",
local_value + 1);
MY_INT = ++local_value;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Output:
Sep 15, 2013 9:49:48 PM com.string.VolatileTest$ChangeMaker run
INFO: Incrementing MY_INT to 1
Sep 15, 2013 9:49:48 PM com.string.VolatileTest$ChangeListener run
INFO: Got Change for MY_INT : 1
Sep 15, 2013 9:49:49 PM com.string.VolatileTest$ChangeMaker run
INFO: Incrementing MY_INT to 2
Sep 15, 2013 9:49:49 PM com.string.VolatileTest$ChangeListener run
INFO: Got Change for MY_INT : 2
Sep 15, 2013 9:49:49 PM com.string.VolatileTest$ChangeMaker run
INFO: Incrementing MY_INT to 3
Sep 15, 2013 9:49:49 PM com.string.VolatileTest$ChangeListener run
INFO: Got Change for MY_INT : 3
Sep 15, 2013 9:49:50 PM com.string.VolatileTest$ChangeMaker run
INFO: Incrementing MY_INT to 4
Sep 15, 2013 9:49:50 PM com.string.VolatileTest$ChangeListener run
INFO: Got Change for MY_INT : 4
Sep 15, 2013 9:49:50 PM com.string.VolatileTest$ChangeMaker run
INFO: Incrementing MY_INT to 5
Sep 15, 2013 9:49:50 PM com.string.VolatileTest$ChangeListener run
INFO: Got Change for MY_INT : 5
No comments:
Post a Comment
I'm certainly not an expert, but I'll try my hardest to explain what I do know and research what I don't know.