When Exactly Do You Use the Volatile Keyword in Java

What is the volatile keyword useful for?

volatile has semantics for memory visibility. Basically, the value of a volatile field becomes visible to all readers (other threads in particular) after a write operation completes on it. Without volatile, readers could see some non-updated value.

To answer your question: Yes, I use a volatile variable to control whether some code continues a loop. The loop tests the volatile value and continues if it is true. The condition can be set to false by calling a "stop" method. The loop sees false and terminates when it tests the value after the stop method completes execution.

The book "Java Concurrency in Practice," which I highly recommend, gives a good explanation of volatile. This book is written by the same person who wrote the IBM article that is referenced in the question (in fact, he cites his book at the bottom of that article). My use of volatile is what his article calls the "pattern 1 status flag."

If you want to learn more about how volatile works under the hood, read up on the Java memory model. If you want to go beyond that level, check out a good computer architecture book like Hennessy & Patterson and read about cache coherence and cache consistency.

When exactly do you use the volatile keyword in Java?

You basically use it when you want to let a member variable be accessed by multiple threads but do not need compound atomicity (not sure if this is the right terminology).

class BadExample {
private volatile int counter;

public void hit(){
/* This operation is in fact two operations:
* 1) int tmp = this.counter;
* 2) this.counter = tmp + 1;
* and is thus broken (counter becomes fewer
* than the accurate amount).
*/
counter++;
}
}

the above is a bad example, because you need compound atomicity.

 class BadExampleFixed {
private int counter;

public synchronized void hit(){
/*
* Only one thread performs action (1), (2) at a time
* "atomically", in the sense that other threads can not
* observe the intermediate state between (1) and (2).
* Therefore, the counter will be accurate.
*/
counter++;
}
}

Now to a valid example:

 class GoodExample {
private static volatile int temperature;

//Called by some other thread than main
public static void todaysTemperature(int temp){
// This operation is a single operation, so you
// do not need compound atomicity
temperature = temp;
}

public static void main(String[] args) throws Exception{
while(true){
Thread.sleep(2000);
System.out.println("Today's temperature is "+temperature);
}
}
}

Now, why can't you just use private static int temperature? In fact you can (in the sense that that your program won't blow up or something), but the change to temperature by the other thread may or may not be "visible" to the main thread.

Basically this means that it is even possible that your app. keeps writing Today's temperature is 0 forever if you don't use volatile (in practice, the value tends to become eventually visible. However, you should not risk not using volatile when necessary, since it can lead to nasty bugs (caused by in-completely constructed objects etc.).

If you put volatile keyword on something that doesn't need volatile, it won't affect your code's correctness (i.e. the behaviour will not change). In terms of performance, it will depend on the JVM implementation. In theory you might get a tiny performance degradation because the compiler can't do reordering optimisations, have to invalidate CPU cache etc., but then again the compiler could prove that your field cannot ever be accessed by multiple threads and remove the effect of volatile keyword completely and compile it to identical instructions.

EDIT:
Response to this comment:

Ok, but why can't we make todaysTemperature synchronized and create a synchronized getter for temperature?

You can and it will behave correctly. Anything that you can with volatile can be done with synchronized, but not vice versa. There are two reasons you might prefer volatile if you can:

  1. Less bug prone: This depends on the context, but in many cases using volatile is less prone to concurrency bugs, like blocking while holding the lock, deadlocks etc.
  2. More performant: In most JVM implementations, volatile can have significantly higher throughput and better latency. However in most applications the difference is too small to matter.

Volatile keyword in Java - Clarification

volatile is a field modifier, while synchronized modifies code blocks and methods. So we can specify three variations of a simple accessor using those two keywords:

     int i1;
int geti1() {return i1;}

volatile int i2;
int geti2() {return i2;}

int i3;
synchronized int geti3() {return i3;}

geti1() accesses the value currently stored in i1 in the current thread.
Threads can have local copies of variables, and the data does not have to be the same as the data held in other threads.In particular, another thread may have updated i1 in it's thread, but the value in the current thread could be different from that updated value. In fact Java has the idea of a "main" memory, and this is the memory that holds the current "correct" value for variables. Threads can have their own copy of data for variables, and the thread copy can be different from the "main" memory. So in fact, it is possible for the "main" memory to have a value of 1 for i1, for thread1 to have a value of 2 for i1 and for thread2 to have a value of 3 for i1 if thread1 and thread2 have both updated i1 but those updated value has not yet been propagated to "main" memory or other threads.

On the other hand, geti2() effectively accesses the value of i2 from "main" memory. A volatile variable is not allowed to have a local copy of a variable that is different from the value currently held in "main" memory. Effectively, a variable declared volatile must have it's data synchronized across all threads, so that whenever you access or update the variable in any thread, all other threads immediately see the same value. Generally volatile variables have a higher access and update overhead than "plain" variables. Generally threads are allowed to have their own copy of data is for better efficiency.

There are two differences between volitile and synchronized.

Firstly synchronized obtains and releases locks on monitors which can force only one thread at a time to execute a code block. That's the fairly well known aspect to synchronized. But synchronized also synchronizes memory. In fact synchronized synchronizes the whole of thread memory with "main" memory. So executing geti3() does the following:

  1. The thread acquires the lock on the monitor for object this .
  2. The thread memory flushes all its variables, i.e. it has all of its variables effectively read from "main" memory .
  3. The code block is executed (in this case setting the return value to the current value of i3, which may have just been reset from "main" memory).
  4. (Any changes to variables would normally now be written out to "main" memory, but for geti3() we have no changes.)
  5. The thread releases the lock on the monitor for object this.

So where volatile only synchronizes the value of one variable between thread memory and "main" memory, synchronized synchronizes the value of all variables between thread memory and "main" memory, and locks and releases a monitor to boot. Clearly synchronized is likely to have more overhead than volatile.

http://javaexp.blogspot.com/2007/12/difference-between-volatile-and.html

Volatile keyword in java under the hood

For the exact meaning of keywords such as volatile, look at the Java Language Specification to see the official meaning.

JLS paragraph 8.3.1.4 explains what volatile means:

A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable (§17.4).

Paragraph 17.4 explains the Java Memory Model. The memory model gives you certain guarantees about what happens to data after each statement in a program.

If you study that carefully, you'll find that volatile means that if you write to a volatile variable, you have the guarantee that other threads will see what was written. How this is implemented in practice is deliberately not specified. It may be implemented by forcing a write to main memory, but JVM implementers are free to choose a different, possibly more efficient mechanism.

So, strictly speaking, your teacher is right. It does not necessarily mean that the value is written to main memory; although in practice this might well be the case - but it depends on the particular JVM implementation.

Purpose/advantages of volatile

When a multithreaded program is running, and there is some shared variable which isn't declared as volatile, what these threads do is create a local copy of the variable, and work on the local copy instead. So the changes on the variable aren't reflected. This local copy is created because cached memory access is much faster compared to accessing variables from main memory.

When you declare a variable as volatile, it tells the program NOT to create any local copy of the variable and use the variable directly from the main memory.

By declaring a variable as volatile, we are telling the system that its value can change unexpectedly from anywhere, so always use the value which is kept in the main memory and always make changes to the value of the variable in the main memory and not create any local copies of the variable.

Note that volatile is not a substitute for synchronization, and when a field is declared volatile, the compiler and runtime are put on notice that this variable is shared and that operations on it should not be reordered with other memory operations. Volatile variables are not cached in registers or in caches where they are hidden from other processors, so a read of a volatile variable always returns the most recent write by any thread.



Related Topics



Leave a reply



Submit