Java Atomic Classes for Lock-Free Synchronization

Atomic Classes

The java.util.concurrent.atomic package provides a way to execute value assignment and lookup operations atomically at the hardware level.

  • AtomicBoolean
  • AtomicInteger
  • AtomicIntegerArray
  • AtomicLong
  • AtomicLongArray

By using these classes, it becomes possible to synchronize processing without using locks such as the synchronized modifier or the ReentrantLock class.
The operations available in each class include the following.

Main methods of Atomic classes

Method Overview Available in AtomicBoolean
get() Gets the current value O
getAndSet(newValue) Gets the current value and sets the specified value O
set(newValue) Sets the specified value O
getAndAdd(delta) Adds the specified value and gets the value before the operation X
addAndGet(delta) Adds the specified value and gets the value after the operation X
getAndDecrement() Decrements the current value by 1 and gets the value before the operation X
decrementAndGet() Decrements the current value by 1 and gets the value after the operation X
getAndIncrement() Increments the current value by 1 and gets the value before the operation X
incrementAndGet() Increments the current value by 1 and gets the value after the operation X

Usage Example

The following rewrites the example using the synchronized modifier, the increment method, with the AtomicInteger class. The standard “i++” operation is not atomic, but the AtomicInteger#getAndIncrement method is atomic, so another thread does not interrupt the process of reading the value, incrementing it, and assigning it again.

AtomicSample.java

package com.devkuma.basic.atomic;

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicSample {
    private AtomicInteger count = new AtomicInteger();

    public static void main(String[] args) {
        AtomicSample as = new AtomicSample();
        as.execute();
    }

    public void execute() {
        final int THREAD_MAX = 300000;
        Thread[] ts = new Thread[THREAD_MAX];
        for (int i = 0; i < THREAD_MAX; i++) {
            ts[i] = new Thread(new MyThread(this));
            ts[i].start();
        }
        for (int i = 0; i < THREAD_MAX; i++) {
            try {
                ts[i].join();
            } catch (InterruptedException e) {
                System.out.println(e);
            }
        }
        System.out.println(count);
    }

    public void increment() {
        count.getAndIncrement();
    }

    private static class MyThread implements Runnable {
        private AtomicSample _counter;

        public MyThread(AtomicSample counter) {
            this._counter = counter;
        }

        @Override
        public void run() {
            _counter.increment();
        }
    }
}

Result:

300000