12
6

More than 3 years have passed since last update.

AtomicReference について私的なメモ

Posted at

コードリーディングをしていると、AtomicReference というクラスに当たったので、調べてみた。

AtmoicReference とは

リファレンスによると

アトミックに更新されるオブジェクトのリファレンス

との事。これだけだとわからないけど、コンカレントプログラミングを実施する際に、シェアするオブジェクトで更新したいものを保持しておく。syncronize はコスト高だし、violatileキーワード は書き込みを同時にされたら破綻する。

volatile

脱線するが、 volatile キーワードの意図するところは、変数の参照を、CPUキャッシュではなく、メインメモリを参照することを保証することにある。このキーワードがない変数は、通常、CPUキャッシュを参照する。複数のCPUがあるシステムの場合、同じ値を参照するとは限らない。そこで、volatile キーワードをつけると、実行しているCPUが違っても、メインメモリを参照するので、同じものをリファレンスすることが保証される。よって、「可視性の保証」ともいわれる。ちなみにvolatile の意味は移り変わりやすい的な意味合い。

private volatile int counter = 0;

ちなみに、理解するのに、このサイトの説明は最高だった。 Java Concurrency というサイトなので、ほかの記事も期待できそう。

AtomicReference

一方、AtmoicReference は、synchronized でロックをがっつりかけることなく、複数のスレッドから参照、更新をするための仕組みです。

get()

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

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

result

atomic: null
atomic: 10

こんな感じで、型を指定しておくと、その値を保持したり、get() メソッドで参照したりできます。コンストラクタはなにも渡さなければ null で初期化されます。

set()

値のセットです。

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

result

atomic: 100

getAndUpdate()

通常は、set() はそんなに使わないと思います。2つのスレッドで更新されたら、後で更新した値になってしまいます。それでよければそれでよいのですが。そこで、getAndUpdate() のようなメソッドがあります。ラムダ式を渡して、現在の値をもとに更新をかけます。updateget の順番が逆のメソッドもあります。

        UnaryOperator operator = (v) -> (Integer)v + 1;
        System.out.println("atomic getAndUpdate: " + atomic.getAndUpdate(operator));
        System.out.println("atomic after getAndUpdate: " + atomic.get());

        System.out.println("atomic updateAndGet: " + atomic.updateAndGet(operator));

result

atomic getAndUpdate: 20
atomic after getAndUpdate: 21
atomic updateAndGet: 22

compareAndSet()

想定している値だった時のみ書き込むメソッドもあります。戻り値はboolean なので、期待されている値だったかはわかります。これによって、ほかのスレッドで更新されていないことが保証されます。

                # この時点で値は 22 
        atomic.compareAndSet(23, 100);
        System.out.println("compareAndSet maybe not updated: " + atomic.get());

result

compareAndSet maybe not updated: 22

ちなみに、weakCompareAndSet というメソッドがあって、結果も同じだったのでなんだろう?と思ったら、Java8までは実装はcompareAndSetと同じで、Java9 から、deprecated らしいので忘れてよさげです。

Reference

12
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
6