アトミック整数、long、booleanなどは、それぞれのタイプに対してアトミック更新を行うために使用されます。これは、++などの操作を実行するときに競合状態が発生する可能性があるためです。しかし、そのような競合状態が発生する可能性のある参照のさまざまなケースは何ですか?
よろしく、
ケシャフ
アトミック整数、long、booleanなどは、それぞれのタイプに対してアトミック更新を行うために使用されます。これは、++などの操作を実行するときに競合状態が発生する可能性があるためです。しかし、そのような競合状態が発生する可能性のある参照のさまざまなケースは何ですか?
よろしく、
ケシャフ
のよう++
な操作は、複数の目立たない操作(フェッチ、インクリメント、ストア)を伴うため、競合状態の影響を受けます。
参照(a = b
)の設定は単一の操作であるため、競合状態の影響を受けません。
参照型(a.someMethod()
)の操作は、必要なことをすべて実行でき、競合状態の影響を受ける場合と受けない場合があります。
JVMは、参照の更新が不可分操作であることを保証するため、AFAIK参照は競合状態の影響を受けません(たとえばlong
、下位4バイトと上位4バイトが2つの異なるステップで更新される更新とは異なります)。SLaksが指摘したように、唯一の重大なケースは、compareAndSet
本質的にアトミックではないということです。これがネイティブ参照で使用されることはめったにありませんが、AtomicReference
2つ(またはそれ以上)の論理的に共依存する変数を一度に更新する必要がある場合の既知のイディオムです。Java Concurrency in Practiceのセクション15.3.1は、この例を公開しており、を使用しAtomicReference
て1つのアトミック操作で2つの変数(単純なクラスに格納されている)を更新します。
AtomicReference
インターフェイスの一貫性は別として、存在する主な理由は、可視性と安全な公開です。この意味で、アトミック変数は「より良いvolatile
」ものです。
学習目的で、AtomicReferenceを使用してConcurrentLinkQueueを作成しました。
package concurrent.AtomicE;
import java.util.concurrent.atomic.AtomicReference;
public class ConcurrentLinkQueue<V> {
private final AtomicReference<Node> firstNodePointer = new AtomicReference<Node>();
public void fastOffer(final V data){
final Node<V> newNode = new Node<V>(data,Thread.currentThread().getName());
System.out.println(newNode);
AtomicReference<Node> pointer = firstNodePointer;
for(;;){
if(pointer.get() == null){
if(pointer.compareAndSet(null,newNode)){
return;
}
}
pointer = pointer.get().getNext();
}
}
private static class Node<V>{
private AtomicReference<Node> next = new AtomicReference<Node>();
private volatile V data = null;
private String threadName = "";
Node(V data1,String threadName){
this.data = data1;
this.threadName = threadName;
}
@Override
public String toString() {
return "threadName=" + threadName +
", data=" + data;
}
private AtomicReference<Node> getNext() {
return next;
}
private void setNext(AtomicReference<Node> next) {
this.next = next;
}
private V getData() {
return data;
}
private void setData(V data) {
this.data = data;
}
}