Java原子操作AtomicIntegerの使い方
2852 ワード
前言:
JDK 1.5以降のjava.util.concurrent.atomicパッケージには、原子処理クラスが追加されています.AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference.主に高同時環境での効率的なプログラム処理に用いられ、同期処理を簡素化するのに役立つ.
AtomicInteger:
AtomicIntegerは、原子操作を提供するIntegerのクラスです.Java言語では、++iとi++の操作はスレッドが安全ではなく、synchronizedキーワードが使用されることは避けられません.AtomicIntegerは、スレッドを介して安全な加減操作インタフェースを介しています.
まず、AtomicIntegerが提供するインタフェースを見てみましょう.
public final int get()/現在の値を取得public final int getAndSet(int newValue)//現在の値を取得し、新しい値を設定public final int getAndIncrement()/現在の値を取得し、public final int getAndDecrement()/現在の値を増加し、public final int getAndAdd(int delta)//現在の値を減少し、予想される値を加算
次に、AtomicIntegerのメリットを2つの簡単な例で見てみましょう.
通常のスレッド同期:
AtomicIntegerを使用するには:
上記の例から、AtomicIntegerを使用することは非常に安全であることがわかります.AtomicIntegerはハードウェアが原子操作命令を提供することによって実現されるからです.激しい競争ではない場合、コストはより小さく、速度はより速い.
AtomicIntegerが非ブロックアルゴリズムを使用して同時制御を実現する方法を見てみましょう.AtomicIntegerのキードメインは3つしかありません.
ここでunsafeはjavaが提供するオブジェクトメモリアドレスへのアクセスを取得するクラスであり、注釈は明確に書かれており、更新操作時に「比較して置き換える」役割を果たす.実はAtomicIntegerのツールです.valueOffsetは、value自体のメモリの安価なアドレスを記録するために使用され、この記録は、主に更新操作でメモリの中でvalueの位置を見つけるために使用され、比較しやすい.注意:valueは整数を格納するための時間変数です.ここでvolatileと宣言されるのは、更新操作時に現在のスレッドがvalueの最新の値を取得できることを保証するためです(同時環境では、valueが他のスレッドに更新されている可能性があります).ここでは、自己増加コードを例に、この同時制御のコアアルゴリズムを見ることができます.
利点のまとめ:最大の利点は、マルチスレッドの優先度の逆転とデッドロックの発生を回避し、高同時処理でのパフォーマンスを向上させることです.
拡張リンク:http://www.ibm.com/developerworks/cn/java/j-jtp11234/
JDK 1.5以降のjava.util.concurrent.atomicパッケージには、原子処理クラスが追加されています.AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference.主に高同時環境での効率的なプログラム処理に用いられ、同期処理を簡素化するのに役立つ.
AtomicInteger:
AtomicIntegerは、原子操作を提供するIntegerのクラスです.Java言語では、++iとi++の操作はスレッドが安全ではなく、synchronizedキーワードが使用されることは避けられません.AtomicIntegerは、スレッドを介して安全な加減操作インタフェースを介しています.
まず、AtomicIntegerが提供するインタフェースを見てみましょう.
public final int get()/現在の値を取得public final int getAndSet(int newValue)//現在の値を取得し、新しい値を設定public final int getAndIncrement()/現在の値を取得し、public final int getAndDecrement()/現在の値を増加し、public final int getAndAdd(int delta)//現在の値を減少し、予想される値を加算
次に、AtomicIntegerのメリットを2つの簡単な例で見てみましょう.
通常のスレッド同期:
class Test2 {
private volatile int count = 0;
public synchronized void increment() {
count++; // count++,
}
public int getCount() {
return count;
}
}
AtomicIntegerを使用するには:
class Test2 {
private AtomicInteger count = new AtomicInteger();
public void increment() {
count.incrementAndGet();
}
// AtomicInteger , , 。
public int getCount() {
return count.get();
}
}
上記の例から、AtomicIntegerを使用することは非常に安全であることがわかります.AtomicIntegerはハードウェアが原子操作命令を提供することによって実現されるからです.激しい競争ではない場合、コストはより小さく、速度はより速い.
AtomicIntegerが非ブロックアルゴリズムを使用して同時制御を実現する方法を見てみましょう.AtomicIntegerのキードメインは3つしかありません.
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset (AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) {
throw new Error(ex);
}
}
private volatile int value;
ここでunsafeはjavaが提供するオブジェクトメモリアドレスへのアクセスを取得するクラスであり、注釈は明確に書かれており、更新操作時に「比較して置き換える」役割を果たす.実はAtomicIntegerのツールです.valueOffsetは、value自体のメモリの安価なアドレスを記録するために使用され、この記録は、主に更新操作でメモリの中でvalueの位置を見つけるために使用され、比較しやすい.注意:valueは整数を格納するための時間変数です.ここでvolatileと宣言されるのは、更新操作時に現在のスレッドがvalueの最新の値を取得できることを保証するためです(同時環境では、valueが他のスレッドに更新されている可能性があります).ここでは、自己増加コードを例に、この同時制御のコアアルゴリズムを見ることができます.
/**
*Atomicallyincrementsbyonethecurrentvalue.
*
*@returntheupdatedvalue
*/
publicfinalintincrementAndGet(){
for(;;){
// value
intcurrent=get();
intnext=current+1;
if(compareAndSet(current,next))
returnnext;
}
}
publicfinalbooleancompareAndSet(intexpect,intupdate){
// unsafe native , CAS
returnunsafe.compareAndSwapInt(this,valueOffset,expect,update);
}
利点のまとめ:最大の利点は、マルチスレッドの優先度の逆転とデッドロックの発生を回避し、高同時処理でのパフォーマンスを向上させることです.
拡張リンク:http://www.ibm.com/developerworks/cn/java/j-jtp11234/