Monday 23 January 2012

Difference Between volatile and synchronized in Java

Before discussing the difference between volatile and synchronized we have to know a little about java memory model,if one instance or static variable is shared among multiple threads,how it is stored in memory.Consider one example

class Counter
{
static int count;

static void setCount(int cnt){
count=cnt;
}
static int getCount(){
return count;
}}

Two threads thread1 and thread2 are sharing this Counter.count variable.
Both threads have a working copy(i.e cache) of this count variable ,initial value of this local copy gets from original counter variable stored in main memory .The local working copy of count variable will re-sync with the original count variable at a particular interval of time. i.e.



where
-------------> means that each working copy of count gets initial value from the original count variable in the main memory.
<-----------> means re-sync of the value of each local working copy with that in main memory.

In the case of an instance or static variable ,re-sync happens at a particular interval of time.This may lead to some inconsistency in the value of the variable ,if it is shared among multiple threads.

Consider our above example,static count variable,thread1 and thread2 concurrently accessing it .Imagine a scenario as follows

STEP1:Main Memory:count=10(initial value of original variable)
STEP2:Thread1 creates local working copy and gets initial value from main memory(i.e. Thread1:count=10).
STEP3:Thread2 creates local working copy and gets initial value from main memory(i.e. Thread2:count=10).
STEP4:Thread1 increments count value by 10 ,after some time re-sync with main memory ( now Thread1:count=20 ,Thread2:count=10 and Main:count=20).

Thread2.count is not yet re-sync with the main memory.Hence thread2 is still using an old value.
How can we solve this problem ? .We have to enforce the re-sync operation during variable access and after updating the variable. i.e. whenever a thread is using its local working copy of a variable ,we have to re-sync its value with that in main memory.

How can we implement it ??
We are very lucky, java is providing two ways i.e. volatile and synchronized to handle this issue.There is a little difference in which scenario both of them are using.Don't worry !!.We will discuss it.

Volatile

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.

Consider the example given below

class Count{

volatile static int count;

static void setCount(int cnt){
count=cnt;
}
static int getCount(){
return count;
}
}

The static variable count is declared with the modifier volatile.Here whenever a thread invokes the getCount() method ,
  1. local working copy's value updates to the latest by a re-sync with original variable.
  2. Returns the latest value to the thread.

Similarly whenever a thread invokes the setCount(int cnt) method,
  1. Set the new value,cnt to the local working copy.
  2. Updates the working copy's value with the original variable in main memory by a re-sync.
Advantages of Volatile
  • volatile supports concurrency(NOTE:synchronized not support this).
  • The thread not acquires the lock on the monitor for object this.Hence reduces the overhead.
Disadvantages of Volatile
  • Whenever a volatile variable is accessed or modified a re-sync occurs.Hence if there is more number of volatile variables ,it will create overhead.
  • We can't use volatile variable for a read-update-write operation,because it is not an atomic operation.i.e. if you do a 'count++' for a volatile count variable that is shared among multiple threads,you can't always expect a correct result.
The 'count++' means  count=count+1 .It includes the following operations

STEP1: get the value of count from main memory.
STEP2:write the updated value back to main memory.

The serial execution of these 2 steps may be interrupted by an another thread.Hence in this scenario we have to use synchronized.

synchronized

Usually synchronized is using to force the serial execution of a block of statements.The synchronized can also be used to perform the memory synchronization,i.e. to do the re-sync of local working copy's value with the original variable.See the example given below

class Count{

static int count;

synchronized static void setCount(int cnt){
count=cnt;
}
synchronized static int getCount(){
return count;
}
}
Now you might think that,is there any need of volatile since synchronized is doing all the functionality.The answer is 'YES'. In some scenario synchronized is more overhead that volatile.

There are two differences between volatile 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 getCount() 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 count, 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 getCount() 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.

The volatile keyword is not a suitable replacement for synchronized blocks most of the time. It is really best used only for those cases when you have a simple and independent value you need to publish to other threads. Things like flags, counters, or oft-created and changed objects. The more threads you have changing the value, the less safe it is to rely on the volatile keyword and the more you likely you need to synchronize access. If the value is part of a calculation then generally it isn't good to use it either unless you also synchronize the calculation as well. 

Summary





volatile
synchronized
Pros
Allows concurrency
Private working memory of all variables within the synchronized block is reconciled with main memory when the lock is obtained and when the lock is released.
Cons
Private working memory is reconciled with main memory on each variable access.
Eliminates concurrency.
Suitable Scenario
When you have a simple and independent value to share among mutilple threads.e.g.
Counters and flags
When you are accessing more number of variables and/or more frequently .In this case using synchronized instead of making all varibles as volatile will reduce overhead.
Unsuitable Scenario
If the variable performing some calculations e.g.
Int incrementCount(){
count++
return count;
}
If you are using synchronized for a variable with independent value like flags,it will create more overhead e.g.
Synchronized boolean getFlag(){return flag;
}

4 comments:

  1. Excellent explanation.

    ReplyDelete
  2. thankxxx....excellent tweet!! very helpful!!

    ReplyDelete
  3. Since Java 5, the volatile keyword forces a happens-before relationship, so the whole thread cache is resynched when a volatile variable is accessed/written not just the volatile variable.
    (http://tutorials.jenkov.com/java-concurrency/volatile.html)

    ReplyDelete