Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simplest and understandable example of volatile keyword in Java

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 shows what would happen if variable wasn't volatile and if it were.

Below code snippet doesn't work as expected (taken from here):

class Test extends Thread {      boolean keepRunning = true;      public void run() {         while (keepRunning) {         }          System.out.println("Thread terminated.");     }      public static void main(String[] args) throws InterruptedException {         Test t = new Test();         t.start();         Thread.sleep(1000);         t.keepRunning = false;         System.out.println("keepRunning set to false.");     } } 

Ideally, if keepRunning wasn't volatile, thread should keep on running indefinitely. But, it does stop after few seconds.

I've got two basic questions:

  • Can anyone explain volatile with example? Not with theory from JLS.
  • Is volatile substitute for synchronization? Does it achieve atomicity?
like image 899
tmgr Avatar asked Jul 19 '13 14:07

tmgr


People also ask

What is volatile keyword in Java with example?

Volatile keyword is used to modify the value of a variable by different threads. It is also used to make classes thread safe. It means that multiple threads can use a method and instance of the classes at the same time without any problem. The volatile keyword can be used either with primitive type or objects.

What do you know about volatile keyword explain with an example code?

The volatile keyword is intended to prevent the compiler from applying any optimizations on objects that can change in ways that cannot be determined by the compiler. Objects declared as volatile are omitted from optimization because their values can be changed by code outside the scope of current code at any time.

What is the volatile keyword useful for?

The volatile keyword prevents the compiler from performing optimization on code involving volatile objects, thus ensuring that each volatile variable assignment and read has a corresponding memory access.

Which of the following best describes volatile keyword?

C's volatile keyword is a qualifier that is applied to a variable when it is declared. It tells the compiler that the value of the variable may change at any time--without any action being taken by the code the compiler finds nearby.


2 Answers

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.

like image 113
Narendra Pathai Avatar answered Oct 29 '22 00:10

Narendra Pathai


For your particular example: if not declared volatile the server JVM could hoist the keepRunning variable out of the loop because it is not modified in the loop (turning it into an infinite loop), but the client JVM would not. That is why you see different results.

General explanation about volatile variables follows:

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.

The visibility effects of volatile variables extend beyond the value of the volatile variable itself. When thread A writes to a volatile variable and subsequently thread B reads that same variable, the values of all variables that were visible to A prior to writing to the volatile variable become visible to B after reading the volatile variable.

The most common use for volatile variables is as a completion, interruption, or status flag:

  volatile boolean flag;   while (!flag)  {      // do something untill flag is true   } 

Volatile variables can be used for other kinds of state information, but more care is required when attempting this. For example, the semantics of volatile are not strong enough to make the increment operation (count++) atomic, unless you can guarantee that the variable is written only from a single thread.

Locking can guarantee both visibility and atomicity; volatile variables can only guarantee visibility.

You can use volatile variables only when all the following criteria are met:

  • Writes to the variable do not depend on its current value, or you can ensure that only a single thread ever updates the value;
  • The variable does not participate in invariants with other state variables; and
  • Locking is not required for any other reason while the variable is being accessed.

Debugging tip: be sure to always specify the -server JVM command line switch when invoking the JVM, even for development and testing. The server JVM performs more optimization than the client JVM, such as hoisting variables out of a loop that are not modified in the loop; code that might appear to work in the development environment (client JVM) can break in the deployment environment (server JVM).

This is an excerpt from "Java Concurrency in Practice", the best book you can find on this subject.

like image 21
Sokolov Avatar answered Oct 28 '22 22:10

Sokolov