Java - AtomicReference使用方法

AtomicReferenceはVクラス(Generic)のオブジェクトをwrappingクラスです。 AtomicReferenceクラスは、マルチスレッド環境での同時実行を保証します。

Javaで同時実行の問題を解決するための3つの方法があります。

  • "volatile"は、Thread1で書き、Thread2で読み取る場合のみ同時実行を保証します。二つのスレッドで書いた場合、問題になることがあります
  • "synchronized"を使えば、安全に同時実行を保証することができます。しかし、コストが最も大きい
  • Atomicクラスは、(CAS compare-and-swap)を利用して、同時実行を保証します。複数のスレッドからのデータをwriteしても問題はありません

AtomicReferenceはsynchronizedよりも少ないコストで同時実行を保証することができます。

AtomicReferenceを使用する方法について説明します。

オブジェクトの作成

AtomicReferenceはGeneric classで実装されて、様々なクラスと一緒に使用することができます。

Integerオブジェクトを持つ AtomicReference<Integer>を例に作成してみましょう。

コンストラクタの初期値を渡すことができ、入力しない場合、オブジェクトはnullに初期化されます。

public void atomicReference1() {
    AtomicReference<Integer> atomic = new AtomicReference<>();
    System.out.println("atomic : " + atomic.get());

    AtomicReference<Integer> atomic2 = new AtomicReference<>(10);
    System.out.println("atomic2 : " + atomic2.get());
}

結果

atomic : null
atomic2 : 10

get(), set(), getAndSet()

AtomicReferenceの値を set(V newValue)メソッドを、値を読むには get()メソッドを使用します。

public void atomicReference2() {
    AtomicReference<Integer> atomic = new AtomicReference<>();
    System.out.println("value : " + atomic.get());

    atomic.set(100);
    System.out.println("value : " + atomic.get());
}

結果

value : null
value : 100

getAndSet(V newValue)は、現在のvalueを返し、引数として渡された値に更新します。

public void atomicReference3() {
    AtomicReference<Integer> atomic = new AtomicReference<>(10);
    System.out.println("value(before setting) : " + atomic.getAndSet(20));
    System.out.println("value(after setting) : " + atomic.get());
}

結果

value(before setting) : 10
value(after setting) : 20

compareAndSet()

compareAndSet(expect、update)は、現在の値が予想される値(expect)と同じであればupdate値に変更してくれて、trueを返してくれます。 そうでない場合、データの変更はなくfalseを返します。

/**
 * Atomically sets the value to the given updated value
 * if the current value {@code ==} the expected value.
 * @param expect the expected value
 * @param update the new value
 * @return {@code true} if successful. False return indicates that
 * the actual value was not equal to the expected value.
 */
public final boolean compareAndSet(V expect, V update)

以下は、compareAndSet()を使用している例です。現在の値と一致する場合にのみ、データが更新され、trueが返されます。

public void atomicReference4() {
    int expected = 20;
    AtomicReference<Integer> atomic = new AtomicReference<>(10);
    System.out.println("success ? " + atomic.compareAndSet(expected, 100));
    System.out.println("value : " + atomic.get());

    atomic.set(20);
    System.out.println("success ? " + atomic.compareAndSet(expected, 100));
    System.out.println("value : " + atomic.get());
}

結果

success ? false
value : 10
success ? true
value : 100

参考

Related Posts

codechachaCopyright ©2019 codechacha