Java参照を備えたレース条件
-
04-10-2019 - |
質問
原子整数、長い、ブールンなどは、それぞれのタイプにアトミックアップデートを行うために使用されます。これは、それらについて操作を実行する際の人種条件がある可能性があるためです。しかし、そのような人種条件があるかもしれない参照を持つさまざまなケースは何ですか?
よろしくお願いします、
ケシャブ
解決
AFAIK参照は、JVMが参照アップデートが原子動作であることを保証するため、人種状態の対象ではありません(例えば、 long
, 、下4バイトと上の4バイトが2つの異なる手順で更新されます)。 Slaksが指摘したように、唯一の重要なケースは compareAndSet
本質的にアトミックではありません。ネイティブ参照で使用されることはほとんどありませんが、それは既知のイディオムです AtomicReference
2つ(またはそれ以上)の論理依存変数を一度に更新する必要がある場合。 実際のJavaの同時性, 、セクション15.3.1は、この例を公開し、 AtomicReference
1つの原子動作で2つの変数(単純なクラスに保存)を更新する。
の存在の主な理由 AtomicReference
- インターフェイスの一貫性とは別に - です 可視性 と 安全な出版物. 。この意味で、原子変数は「より良い volatile
".
他のヒント
のような操作 ++
複数の慎重な操作(フェッチ、増分、ストア)が含まれるため、レース条件の対象となります。
参照の設定(a = b
)は単一の操作であるため、人種条件の対象ではありません。
参照タイプの操作(a.someMethod()
)彼らが望むすべてのことをすることができます、そして、人種条件の対象となるかもしれないし、そうでないかもしれません。
学習の目的のために、私はAtomicReferenceを使用して同時リンクキューを書きました。
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;
}
}