CASスピンvolatile変数
1234 ワード
まず、AtomicIntegerクラスのgetAndIncrementのソースコードを見てみましょう.
このコードは巧みに書かれています.
1,compareAndSetメソッドは,まず現在値がcurrentに等しいか否かを判断する.
2現在の値=currentの場合、AtomicIntegerの値は他のスレッドによって変更されていないことを示します.
3、現在の値の場合!=Currentは、AtomicIntegerの値が他のスレッドによって変更されたことを示し、このとき再びループ再比較に入る.
getAndIncrementメソッドでは、現在のvalue属性値を取得し、valueに1を加えてローカルのnext変数に値を付与します.しかし、この2つのステップは非スレッドで安全ですが、内部にはデッドサイクルがあり、成功するまでcompareAndSet操作を続けます.つまり、修正の根本はcompareAndSetメソッドにあります.
compareAndSet()メソッドで呼び出されたのはsunであることがわかる.misc.Unsafe.compareAndSwapInt(Object obj,long valueOffset,int expect,int update)メソッド
compareAndSwapIntは、CPUのCAS命令に基づいて実現される.したがって、CASベースの動作はブロックされていないと考えられ、1つのスレッドの失敗または停止は、他のスレッドも失敗または停止を引き起こすことはありません.またCAS操作はCPU原語なので性能が良い.
以上,getAndIncrement()法は原子操作ではない.彼と他の関数がvalueの更新に有効であることを保証しただけです.
彼が利用しているのは衝突検出に基づく楽観的な同時戦略である.この楽観はスレッド数が非常に多い場合,失敗の確率が指数的に増加することが想像できる.
public final int getAndIncrement() {
for (;;) {
int current = get(); // AtomicInteger
int next = current + 1; // 1
if (compareAndSet(current, next)) // compareAndSet
return current;
}
}
このコードは巧みに書かれています.
1,compareAndSetメソッドは,まず現在値がcurrentに等しいか否かを判断する.
2現在の値=currentの場合、AtomicIntegerの値は他のスレッドによって変更されていないことを示します.
3、現在の値の場合!=Currentは、AtomicIntegerの値が他のスレッドによって変更されたことを示し、このとき再びループ再比較に入る.
getAndIncrementメソッドでは、現在のvalue属性値を取得し、valueに1を加えてローカルのnext変数に値を付与します.しかし、この2つのステップは非スレッドで安全ですが、内部にはデッドサイクルがあり、成功するまでcompareAndSet操作を続けます.つまり、修正の根本はcompareAndSetメソッドにあります.
compareAndSet()メソッドで呼び出されたのはsunであることがわかる.misc.Unsafe.compareAndSwapInt(Object obj,long valueOffset,int expect,int update)メソッド
compareAndSwapIntは、CPUのCAS命令に基づいて実現される.したがって、CASベースの動作はブロックされていないと考えられ、1つのスレッドの失敗または停止は、他のスレッドも失敗または停止を引き起こすことはありません.またCAS操作はCPU原語なので性能が良い.
以上,getAndIncrement()法は原子操作ではない.彼と他の関数がvalueの更新に有効であることを保証しただけです.
彼が利用しているのは衝突検出に基づく楽観的な同時戦略である.この楽観はスレッド数が非常に多い場合,失敗の確率が指数的に増加することが想像できる.