Sunday, June 11, 2017

Atomic Operations in java7

Atomic Operations without using java.util.concurrent.atomic package

class Counter {
      int count;

      public synchronized void increment() {
            count++;
      }

      public int getCount() {
            return count;
      }
}

public class NonAtomicOperation extends Thread {
      private Counter counter;

      public NonAtomicOperation(Counter counter) {
            this.counter = counter;
      }

      public static void main(String[] args) throws InterruptedException {
            Counter counter = new Counter();
            NonAtomicOperation thread1 = new NonAtomicOperation(counter);
            NonAtomicOperation thread2 = new NonAtomicOperation(counter);
            thread1.start();
            thread2.start();
            thread1.join();
            thread2.join();
            System.out.println(counter.getCount());
      }

      public void run() {
            for(int i=0;i<1000;i++)
                  counter.increment();
            }
}

Here, we’ve counter object being shared by two threads at once. If synchronized not being used then output won’t be 2000

Please note that count++ isn’t an atomic operation.  So by the time one threads read it's value and increment it by one, other thread has read the older value leading to wrong result.

One way to make it right is by using synchronized keyword, so that one thread at a time access increment() and using join() as well so as to stop main thread to print the value right away.

Second Approach
Here is the updated program that will always output count value as 2000 because AtomicInteger method incrementAndGet() atomically increments the current value by one.

class Counter {
      AtomicInteger count = new AtomicInteger();

      public void increment() {
            /* incrementAndGet() atomically increments the current value by one*/
            count.getAndIncrement();
      }

      public int getCount() {
            return count.intValue();
      }
}

public class NonAtomicOperation extends Thread {
      private Counter counter;

      public NonAtomicOperation(Counter counter) {
            this.counter = counter;
      }

      public static void main(String[] args) throws InterruptedException {
            Counter counter = new Counter();
            NonAtomicOperation thread1 = new NonAtomicOperation(counter);
            NonAtomicOperation thread2 = new NonAtomicOperation(counter);
            thread1.start();
            thread2.start();
            thread1.join();
            thread2.join();
            System.out.println(counter.getCount());
      }

      public void run() {
            for (int i = 0; i < 1000; i++)
                  counter.increment();
      }
}

Output:
2000

Advantages


Benefits of using Concurrency classes for atomic operation is that we don't need to worry about synchronization. This improves code readability and chance of errors are reduced. Also atomic operation concurrency classes are assumed to be more efficient that synchronization which involves locking resources.

No comments:

Post a Comment