Wednesday 7 December 2016

Is operations on primitive types are atomic?

Java support primitive types like byte, int, long etc., following table summarizes the primitive data types and their size in bytes.

Data Type
Size (in bytes)
byte
1
short
2
int
4
long
8
float
4
double
8
char
2

Note: The boolean data type has only two possible values: true and false. This data type represents one bit of information, but its "size" isn't something that's precisely defined.

Writes and reads of primitive types other than long and double are atomic by default. But writes and reads on long, double datatypes are need not be atomic. They depend on implementation of JAVA vendor.

Non-atomic Treatment of double and long
As per the java specification, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write.

How can I make the Write & Read operations on long and double as atomic?
Make the long and double variables as volatile. Writes and reads of volatile long and double values are always atomic. So while working in multi-threaded environment always make the long, double as volatile (or) use some synchronization mechanism (or) use the class AtomicLong.

Let me clarify what is atomicity with an example. I mentioned that, writes and reads of primitives (except long, double) and volatile long, double are atomic. Now go through following code and check whether it is atomic (or) not.

private static int counter = 0;
public void increment() { counter++; }

Do you think the operation counter++ is atomic?
Of course not, the statement 'counter++' is actually combination of three operations
         1. Read the value of variable counter
         2. Increment the value counter by one
         3. Write the updated value to counter

How to make the operation atomic?
By synchronizing the access to the variable counter, you can make the operation atomic.

private static int counter = 0;
public static synchronized void increment() {
   counter++;
}

                          (OR)
private static int counter = 0;
private static final Object LOCK = new Object();

public static void increment() {
   synchronized(LOCK) {
      counter++;
   }
}

You may like



No comments:

Post a Comment