Thursday 27 June 2019

Volatile vs AtomicInteger

Volatile : Visibility 

Volatile without synchronization

Let us take a look at a simple example. We write a program that checks if the printer is running or not. In a simple one-threaded program, we declare a boolean printer_running variable and see if its still true:
boolean printer_running = true;
 
while(printer_running) {
    //do something
}
In a multi-threaded system this code may not work correctly. If some other thread accesses the variable and changes it to false, the thread running this code block may not know about the change immediately. This may result in the loop being executed more than necessary and may result in data integrity problems and it is a hard very hard error to find and fix. A solution to this problem may be to declare the printer_running variable as volatile. This will make all the changes to the variable by one thread be visible to all other threads at once.

volatile boolean printer_running = true;
 
while(printer_running) {
    //do something
}
This is an example of volatile variable without synchronization. This means that the variable can still be accessed by other threads while the code performs changes to it.

Volatile with synchronization

In order for the code to be bullet-proof we need to synchronize the block performing operations on volatile variables:
class Foo {
  private volatile boolean printer_running = true;
  public boolean getStatus() {
    if (printer_running) {
      synchronized(this) {
        while(printer_running) {
            //do something
        }
      }
    }
  return printer_running;
}
This code is an example of a double-checked locking or volatile variable with synchronization. This code ensures that no other thread gets to execute the while() block while at the same time all other threads get to know new updated values of the volatile variable.

Atomic Variables: Compound Operations 


The  Atomic integer is also provided in Java which provides and integer variable which can be read and write properly. It can be accessed by many threads concurrently. It also provides compare and swap instruction support.
private volatile int counter;
 
public int getNextUniqueIndex() {
    return counter++;
}
In this example, multiple threads can change the counter variable and data integrity is affected. Below is the example of using Atomic Integer:
private AtomicInteger counter;
 
public int getNextUniqueIndex() {
    return counter.getAndIncrement();
}
The beauty of atomic int is that it is tread safe and it cannot violate the thread safety because it achieves same synchronization as in atomic boolean, hence get the correct result even multiple threads access it at the same time.