Overview:
Volatile is probably the less known/understood/documented keyword in Java. I have recently read an article on one of my favourite blog about the volatile keyword. The author shows a piece of code where the volatile keyword seems to have an influence. This example was not easy to understand and the role of the volatile keyword on the behaviour of the JVM was not really defined. So I have decided to browse the web to find a better code example for the volatile keyword. After one hour, nothing! Only wrong examples, articles comparing volatile with synchronized and other confused examples where the author seems as lost as the reader...
A Basic Example:
The following show a basic example where volatile is required
01.
public
class
VolatileTest {
02.
private
static
final
Logger LOGGER = MyLoggerFactory.getSimplestLogger();
03.
04.
private
static
volatile
int
MY_INT =
0
;
05.
06.
public
static
void
main(String[] args) {
07.
new
ChangeListener().start();
08.
new
ChangeMaker().start();
09.
}
10.
11.
static
class
ChangeListener
extends
Thread {
12.
@Override
13.
public
void
run() {
14.
int
local_value = MY_INT;
15.
while
( local_value <
5
){
16.
if
( local_value!= MY_INT){
17.
LOGGER.log(Level.INFO,
"Got Change for MY_INT : {0}"
, MY_INT);
18.
local_value= MY_INT;
19.
}
20.
}
21.
}
22.
}
23.
24.
static
class
ChangeMaker
extends
Thread{
25.
@Override
26.
public
void
run() {
27.
28.
int
local_value = MY_INT;
29.
while
(MY_INT <
5
){
30.
LOGGER.log(Level.INFO,
"Incrementing MY_INT to {0}"
, local_value+
1
);
31.
MY_INT = ++local_value;
32.
try
{
33.
Thread.sleep(
500
);
34.
}
catch
(InterruptedException e) { e.printStackTrace(); }
35.
}
36.
}
37.
}
38.
}
With the volatile keyword the output is :
01.
Incrementing MY_INT to
1
02.
Got Change
for
MY_INT :
1
03.
Incrementing MY_INT to
2
04.
Got Change
for
MY_INT :
2
05.
Incrementing MY_INT to
3
06.
Got Change
for
MY_INT :
3
07.
Incrementing MY_INT to
4
08.
Got Change
for
MY_INT :
4
09.
Incrementing MY_INT to
5
10.
Got Change
for
MY_INT :
5
Without the volatile keyword the output is :
1.
Incrementing MY_INT to
1
2.
Incrementing MY_INT to
2
3.
Incrementing MY_INT to
3
4.
Incrementing MY_INT to
4
5.
Incrementing MY_INT to
5
.....And the change listener loop infinitely...
A Simple Explanation:
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...
Never used volatile and never met this problem...
Like all threads issues, it happens under specials circumstances. Really special for this one... My example has big chances to show mainly because the ChangeListener thread is busy, thanks to the loop, and the JVM consider that this thread has no time for updating the local variables. Executing some synchronized methods or adding an other variable which is volatile (or even executing some simple lines of code) could modify the JVM behavior and "correct" this problem...
Why posted this article? .. well i was asked this simple question in an interview. I managed to answer in some way as i have seen it's use in "Single Design Pattern" (when thread safe behavior is required).
Note:
- The above example and behavior is only true for JDK 1.5 and up.
- Volatile is noway a replacement of synchronized keyword. It only deals with shared data visibility between threads.
- The typical use case is simple signaling between threads. One thread sets the signal and the others are only read it.
Comments
Post a Comment