Monday, February 7, 2011

Atomic Variables

Before going to Atomic variables we need to understand following concepts.These are:-
  • Threads and caching by JVM
  • Volatile modifier
  • Locking and synchronization
  • Atomic Operation

Thread and caching by JVM

Difference between threads and process besides process being heavy and threads being lighter is that threads can access the shared state.Where as process are independent of each other and does not share any information.More one process is made up of many threads.

In Java threads can be created by either extending thread class or implementing runnable interface and providing reference to it in thread constructor.However in order to improve the performance JVM provides the cached copy of non volatile variable to each thread so that any updation on those variables happens fast.But it leads to scenario where other thread reads the stale information because local cached copy of non volatile variable has not been synchronized with main register.
This leads to the concept of volatile variables.

What is Volatile modifier ?
When we define variable as volatile,JVM makes sure that every access operation uses the shared memory rather than cached copy.So read and write are atomic/synchronized and visible to all threads.
However volatile variables have a issue, multiple operations like increment/decrement and get ,compare and swap and others are not atomic.So it can lead to data corruption in case of multi-threaded environment. 

Example:- 
private volatile int i=10; 
i++;

Here we are having a volatile int variable ,i.Then we increment its value by 1 by doing i++.
However it involves three operations 
                 -Read the value of i 
                 -Increment the value of i by 1
                 -Set the value of i
So in case of multi-threaded environment,it may happen that while Thread-1 is in the process of incrementing the value.Another thread has changed the value of i.So operation i++ is not fully atomic.

So it leads us to locking

What is Locking?
Locking mechanism makes sure that only one thread is modifying the object since it has exclusive lock on that object and in Java we do locking mostly by using synchronized methods or synchronized blocks.However locking has many issues.Some of them are as follows:-
  •  It impacts performance as in case of multi threaded environment,thread context switching is  expensive.
  • Since at a particular time only one thread can run the synchronized method/block.Other threads are just sitting idle/blocked till lock is released.Basically they are wasting cpu cycles.
  • Moreover if code is not properly written,we can end up having deadlock scenario.

So it leads us to atomic variables.

What are Atomic Variables?
Atomic  variables are nothing but extension of volatile variables to operations besides read and write.It uses underlying hardware instructions that platform provides for concurrent access such as compare and swap.

Moreover unlike synchronization it uses non blocking and collision detection feature to do operations.
Non Blocking means that failure or suspension of one thread does not have any issues on other concurrent threads.
Collision detection assumes that no other thread will be updating the shared data structure and in case any other thread modifies the shared data while current thread is updating the shared data.Current thread will be notified of the collision which can respond appropriately by either retrying or some other mechanism.
Atomic classes are designed primarily as building blocks for implementing non-blocking data structures and related infrastructure classes. The compareAndSet method is not a general replacement for locking. It applies only when critical updates for an object are confined to a single variable.  

Excerpt from Java API Documentation
The memory effects for accesses and updates of atomics generally follow the rules for volatiles, as stated in The Java Language Specification, Third Edition (17.4 Memory Model):
  • get has the memory effects of reading a volatile variable.
  • set has the memory effects of writing (assigning) a volatile variable.
  • lazySet has the memory effects of writing (assigning) a volatile variable except that it permits reorderings with subsequent (but not previous) memory actions that do not themselves impose reordering constraints with ordinary non-volatile writes. Among other usage contexts, lazySet may apply when nulling out, for the sake of garbage collection, a reference that is never accessed again.
  • weakCompareAndSet atomically reads and conditionally writes a variable but does notweakCompareAndSet. create any happens-before orderings, so provides no guarantees with respect to previous or subsequent reads and writes of any variables other than the target of the
  • compareAndSet and all other read-and-update operations such as getAndIncrement have the memory effects of both reading and writing volatile variables.

Since atomic variables does not use synchronization and uses underlying hardware support (compare and swap algorithm and others) and collision detection feature its faster than synchronized block and at the same time it makes sure that concurrent modification does not lead to wrong data.Moreover it neatly encapsulate operations, and they prevent inadvertent access to data from unsynchronized code.

No comments:

Post a Comment