5

Java には AtomicReference クラスが存在します。これは、参照の設定自体がアトミック操作ではないことを意味しますか?

たとえば、これはスレッドセーフではありませんか (返された値を変更できないと仮定して)?:

public void someMethod()
{
   this.someList = Collections.unmodifiableList(new LinkedList<Object>());
}

public List<Object> getReadOnlyList()
{
   return someList;
}

C#ではどうですか?

4

5 に答える 5

3

見過ごされがちな のパッケージの説明では、いくつかの一般的な用途についてjava.util.concurrent.atomic詳しく説明しています。

補遺: 同様に、 のパッケージの説明には、 JLS §17java.util.concurrentで詳述されているいくつかの重要な点が便利に要約されています。

また、あなたが不変であることを意図しており、それへの参照を行うことができる場合、 Final Field Semanticsの潜在的な利点を考慮してください。Listfinal

于 2010-03-05T03:21:09.737 に答える
3

これは、参照の設定自体がアトミック操作ではないことを意味しますか?

参照変数の設定はアトミックですが、アトミック操作は必ずしもスレッドセーフではありません。説明させてください。

アトミックとは、オブザーバー (スレッド) が変数の古い値または新しい値のいずれかを認識し、それ以外のものを認識しないことを意味します。変数を見たときに、すべてのオブザーバーが新しい値を見るわけではありません。(そして、@Tom が指摘するように、参照変数の原子性は、それが参照するオブジェクトの原子性プロパティについては何も言いません。)

すべてのオブザーバーが変数の新しい値を確認するには、何らかの同期が行われている必要があります。変数の更新の場合、これは次の場合に発生します。

  • 変数はvolatile、または
  • 変数へのアクセス/更新は、同じプリミティブ モニター ロックによって同期されます。

関連する「AtomicXxx」クラスにラップされた変数もスレッドセーフになりますが、ロックを回避したい場合やアトミックな「比較と置換」などを実行したい場合は、通常これらのクラスのいずれかを使用します

ただし、これはオブジェクトの参照のスレッドセーフにのみ適用されます。オブジェクトの状態適切に同期されていない場合、スレッドはオブジェクトの属性などの古い値を確認する可能性があります。

于 2010-03-05T04:20:09.057 に答える
3

Java 言語仕様、バージョン 3.0、セクション 17.7 によると:

参照の書き込みと読み取りは、32 ビット値または 64 ビット値として実装されているかどうかに関係なく、常にアトミックです。

AtomicReference を使用すると、アトミック アクションとして比較および設定を実行できます。

これはスレッドセーフではありません:

public boolean changeList(List<Object> oldValue, List<Object> newValue) { 
    if (this.someList == oldValue) {
        // someList could be changed by another thread after that compare,
        // and before this set
        this.someList = newValue;
        return true;
    }
    return false;
}
于 2010-03-05T03:08:54.620 に答える
2

AtomicReference または volatile キーワードを使用せず、参照を読み取るスレッドが書き込みを行ったスレッドではない場合、読み取りスレッドが更新された値を参照するという保証はありません。

これは、マルチ プロセッサ環境で特に当てはまります。volatile キーワードと AtomicReference (基本的な set/get 操作に volatile を内部で使用) は、更新された値がメイン メモリに表示されるように、メモリ バリアとキャッシュ フラッシュを強制します。

于 2010-03-05T03:09:04.410 に答える
1

C#に関しては、これに対する答えを自分で見つけました。参照の設定は、C# 言語仕様のセクション 5.5 によるアトミック操作です。

「次のデータ型の読み取りと書き込みはアトミックです: bool、char、byte、sbyte、short、ushort、uint、int、float、および参照型。さらに、前の基本型を持つ列挙型の読み取りと書き込みlist もアトミックです. long , ulong , double , decimal を含む他の型やユーザー定義型の読み書きは, アトミックであるとは限りません. その目的のために設計されたライブラリ関数以外には,インクリメントまたはデクリメントの場合のように、アトミックな読み取り-変更-書き込みの保証。」

于 2010-03-05T03:24:23.677 に答える