Sunday, September 14, 2014

Atomic Operations Introduction

Traditional multi-threading approaches use locks to protect shared resources.  Synchronization objects like Semaphores provide mechanisms for the programmer to write code that doesn't modify a shared resource concurrently. The synchronization approaches block other threads when one of the thread is modifying a shared resource. Obviously blocked threads are not doing meaningful work waiting for the lock to be released.

Atomic operations on the contrast are based on non-blocking algorithms in which threads waiting for shared resources don't get postponed. Atomic operations are implemented using hardware primitives like compare and swap (CAS) which are atomic instructions used in multi-threading for synchronization.

Java Atomic Classes

Java supports atomic classes that support lock free, thread safe programming on single variables. These classes are defined in java.util.concurrent.atomic package. Some of the key classes include AtomicBoolean, AtomicInteger, AtomicLong, AtomicIntegerArray, AtomicLongArray and AtomicReference.

Some of the key APIs for AtomicInteger class include:
  • AtomicInteger() - Creates a new AtomicInteger that can be updated atomically. Initial value is set to 0.
  • AtomicInteger(int value) - Creates a new AtomicInteger with the specified initial value.
  • boolean compareAndSet(int expect, int value) - Atomically set the value if the current value is same as expected value.
  • int getAndSet(int newVal) - Atomically sets to new value and returns old value.
  • int getAndIncrement() - Atomically increments the current value and returns old value.
  • int incrementAndGet() - Atomically increments the current value and returns new value.
  • int getAndAdd(int delta) - Atomically adds the delta to current value and returns old value.
Refer to this link for more details.

Java AtomicInteger Example

In this example we have a producer and consumer acting up on a AtomicInteger counter to get lock free synchronization.

package com.sourcetricks.atomic;

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicOpsExample {

  private static AtomicInteger count = new AtomicInteger(0);
  
  // Producer thread. Counts up the resource.
  private static class ProducerTask implements Runnable {

    @Override
      public void run() {
          for ( int i = 0; i < 10; i++ ) {           
            count.getAndIncrement();
            System.out.println("Counting up");   
          }                
      }     
  }

  // Consumer thread. Counts down the resource.
  private static class ConsumerTask implements Runnable {

    @Override
      public void run() {
          for ( int i = 0; i < 3; i++ ) {            
            count.getAndDecrement();
            System.out.println("Counting down");
          }                
      }     
  }
    
  public static void main(String[] args) {
    Thread producer = new Thread(new ProducerTask());
    Thread consumer = new Thread(new ConsumerTask());
    producer.start();
    consumer.start();   
  }
}

This program produces the following output.

Counting up
Counting up
Counting up
Counting up
Counting up
Counting down
Counting down
Counting down
Counting up
Counting up
Counting up
Counting up
Counting up

Refer to this link for more Java Tutorials.

0 comments :

Post a Comment

Contact Form

Name

Email *

Message *

Back to Top