AtomicXxxxxクラス
ロックフリーな同期処理を実装する – AtomicXxxxxクラスjava.util.concurrent.atomicパッケージでは、値の代入/取得といった処理をハードウェアレベルでアトミックに実行する手段を提供します。
・AtomicBoolean
・AtomicInteger
・AtomicIntegerArray
・AtomicLong
・AtomicLongArray
これらのクラスを利用することで、synchronized修飾子、ReentrantLockクラスのようにロックを取得することなく、処理を同期させることが可能になります。
それぞれのクラスで利用できる処理には、以下のようなものがあります。
AtomicXxxxxクラスの主なメソッド(*はAtomicBooleanでは利用できないもの) | |
---|---|
メソッド | 概要 |
get() | 現在の値を取得 |
getAndSet(newValue) | 現在の値を取得し、指定された値を設定 |
set(newValue) | 指定された値を設定 |
*getAndAdd(delta) | 指定された値を追加(操作前の値を取得) |
*addAndGet(delta) | 指定された値を追加(操作後の値を取得) |
*getAndDecrement() | 現在の値を1デクリメント(操作前の値を取得) |
*decrementAndGet() | 現在の値を1デクリメント(操作後の値を取得) |
*getAndIncrement() | 現在の値を1インクリメント(操作前の値を取得) |
*incrementAndGet() | 現在の値を1インクリメント(操作後の値を取得) |
以下は、synchronized修飾子の項のサンプル(incrementメソッド)をAtomicIntegerクラスで書き換えたものです。標準的な「i++」演算はアトミックではありませんが、AtomicInteger#getAndIncrementメソッドはアトミックなので、値の取得からインクリメント、再代入の過程に他のスレッドが割り込むことはありません。
AtomicSample.java
package com.example.mynavi.thread; 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(); } } }