Close

Java - Atomic access to array elements with AtomicIntegerArray, AtomicLongArray, and AtomicReferenceArray

[Last Updated: May 24, 2018]

The AtomicIntegerArray, AtomicLongArray, and AtomicReferenceArray classes further extend atomic operation support to arrays of int, long and reference types respectively.
These classes have index based methods (e.g. get(int i), set(int i, newValue) etc) supporting atomic operations on an array element at that specific index position.

Example

In following example we will see how to use AtomicLongArray. We are going to assign arrays elements with sums of X^n where each element of the array will have different base X i.e. 2, 3,...6, each with exponents 1,2,3,4.... 10. The sum will be accumulated by different thread:

package com.logicbig.example;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLongArray;
import java.util.stream.IntStream;

public class AtomicLongArrayExample {
  private static int len = 5;
  private static AtomicLongArray sumArray = new AtomicLongArray(len);

  public static void main(String[] args) throws InterruptedException {
      for (int k = 0; k < 3; k++) {
          IntStream.range(0, len).forEach(i -> sumArray.set(i, 0L));
          ExecutorService es = Executors.newFixedThreadPool(50);
          for (int b = 2; b < len + 2; b++) {
              for (int i = 1; i <= 10; i++) {
                  int exponent = i;
                  int base = b;
                  es.execute(() -> sumArray.accumulateAndGet(base - 2,
                          (long) Math.pow(base, exponent),
                          (d1, d2) -> d1 + d2));
              }
          }
          es.shutdown();
          es.awaitTermination(10, TimeUnit.MINUTES);
          IntStream.range(0, len)
                   .forEach(i -> System.out.println(sumArray.get(i)));

          System.out.println("-----------");
      }
  }
}
2046
88572
1398100
12207030
72559410
-----------
2046
88572
1398100
12207030
72559410
-----------
2046
88572
1398100
12207030
72559410
-----------

We repeated the whole process 3 times and found that sums were always same.

Without Atomic Access

Let's see how the code will look like without AtomicLongArray and what will be the output.

package com.logicbig.example;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

public class NoAtomicLongArrayExample {
  private static int len = 5;
  private static Long[] sumArray = new Long[len];

  public static void main(String[] args) throws InterruptedException {
      for (int k = 0; k < 3; k++) {
          IntStream.range(0, len).forEach(i -> sumArray[i] = 0L);
          ExecutorService es = Executors.newFixedThreadPool(50);
          for (int b = 2; b < len + 2; b++) {
              for (int i = 1; i <= 10; i++) {
                  int exponent = i;
                  int base = b;
                  es.execute(() -> {
                      sumArray[base - 2] += (long) Math.pow(base, exponent);
                  });
              }
          }
          es.shutdown();
          es.awaitTermination(10, TimeUnit.MINUTES);
          IntStream.range(0, len).forEach(i -> System.out.println(sumArray[i]));
          System.out.println("-----------");
      }
  }
}
764
88572
1398100
12207030
72559410
-----------
2046
88572
1398100
12125780
72559410
-----------
2046
88572
1398100
12207030
72559410
-----------

The sums are not always same, that's because the compound assignment operation '+=' is not atomic.

Example Project

Dependencies and Technologies Used:

  • JDK 10
  • Maven 3.3.9

Atomic Array Example Select All Download
  • atomic-array-example
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • AtomicLongArrayExample.java

    See Also