Javaの並行性-AtomicIntegerクラス

java.util.concurrent.atomic.AtomicIntegerクラスは、アトミックに読み書きできる基礎となるint値に対する操作を提供し、高度なアトミック操作も含みます。AtomicIntegerは、基になるint変数に対するアトミック操作をサポートします。揮発性変数の読み取りと書き込みのように機能するgetメソッドとsetメソッドがあります。つまり、セットには、同じ変数に対する後続のgetとの発生前の関係があります。アトミックcompareAndSetメソッドには、これらのメモリ整合性機能もあります。

AtomicIntegerメソッド

以下は、AtomicIntegerクラスで使用可能な重要なメソッドのリストです。

シニア番号 方法と説明
1

public int addAndGet(int delta)

指定された値を現在の値に原子的に追加します。

2

public boolean compareAndSet(int expect, int update)

現在の値が期待値と同じである場合、原子的に値を指定された更新値に設定します。

3

public int decrementAndGet()

原子的に現在の値を1つ減らします。

4

public double doubleValue()

指定された数値の値をdoubleとして返します。

5

public float floatValue()

指定された数値の値をfloatとして返します。

6

public int get()

現在の値を取得します。

7

public int getAndAdd(int delta)

指定された値を現在の値にアトミックに追加します。

8

public int getAndDecrement()

原子的に現在の値を1つ減らします。

9

public int getAndIncrement()

現在の値を1つ原子的にインクリメントします。

10

public int getAndSet(int newValue)

原子的に指定された値に設定され、古い値を返します。

11

public int incrementAndGet()

現在の値を1つ原子的にインクリメントします。

12

public int intValue()

指定された数値の値をintとして返します。

13

public void lazySet(int newValue)

最終的には指定された値に設定されます。

14

public long longValue()

指定された数値の値をlongとして返します。

15

public void set(int newValue)

指定された値に設定します。

16

public String toString()

現在の値の文字列表現を返します。

17

public boolean weakCompareAndSet(int expect, int update)

現在の値が期待値と同じである場合、原子的に値を指定された更新値に設定します。

次のTestThreadプログラムは、スレッドベースの環境でのカウンターの安全でない実装を示しています。

public class TestThread {

   static class Counter {
      private int c = 0;

      public void increment() {
         c++;
      }

      public int value() {
         return c;
      }
   }
   
   public static void main(final String[] arguments) throws InterruptedException {
      final Counter counter = new Counter();
      
      //1000 threads
      for(int i = 0; i < 1000 ; i++) {
         
         new Thread(new Runnable() {
            
            public void run() {
               counter.increment();
            }
         }).start(); 
      }  
      Thread.sleep(6000);
      System.out.println("Final number (should be 1000): " + counter.value());
   }  
}

これにより、コンピューターの速度とスレッドのインターリーブによっては、次の結果が生じる場合があります。

出力

Final number (should be 1000): 1000

次のTestThreadプログラムは、スレッドベースの環境でAtomicIntegerを使用したカウンターの安全な実装を示しています。

import java.util.concurrent.atomic.AtomicInteger;

public class TestThread {

   static class Counter {
      private AtomicInteger c = new AtomicInteger(0);

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

      public int value() {
         return c.get();
      }
   }
   
   public static void main(final String[] arguments) throws InterruptedException {
      final Counter counter = new Counter();
      
      //1000 threads
      for(int i = 0; i < 1000 ; i++) {

         new Thread(new Runnable() {
            public void run() {
               counter.increment();
            }
         }).start(); 
      }  
      Thread.sleep(6000);
      System.out.println("Final number (should be 1000): " + counter.value());
   }
}

これにより、次の結果が得られます。

出力

Final number (should be 1000): 1000