4

注:: この質問はメモリの可視性に関するものであり、「パブリック」、「プライベート」などではありません。

次のクラスがあるとしましょう:

public class Data {
    public final byte[] array;
    public final int offset, length;
    public Data(byte[] array, int offset, int length) {...}
    ...
}

(上記の配列の要素は、示されていないメソッドによって変更できます。)

ここで、別のクラスに指定されたデータを含むキューがあるとします。

final ConcurrentLinkedQueue<Data> queue = new ConcurrentLinkedQueue<>();

ここで、キューを持つクラスに次のコードがあるとします。

Data data = queue.poll();
... code for reading the elements in the data object.

私の質問は次のとおりです。キューのポーリング前に設定された配列内の要素は、キューからデータをポーリングしたスレッドに表示されることが保証されていますか?

キューのポーリング後に設定された要素がリーダーに表示されないことを理解しています。キューのポーリング前に設定された要素にのみ関心があります。

そうでない場合は、ポーリングメソッドを呼び出した後に配置された次のコードが配列の可視性を確保することを理解しています

data = new Data(data.array, data.offset, data.length);

オブジェクトの構築により、オブジェクトのフィールドの完全な可視性が保証されるためです。これは正しいです?

ありがとう!

4

2 に答える 2

4

ドキュメントには次のように書かれています。

java.util.concurrentとそのサブパッケージのすべてのクラスのメソッドは、これらの保証をより高いレベルの同期に拡張します。特に:

オブジェクトを同時コレクションに配置する前のスレッド内のアクションが発生します-別のスレッド内のコレクションからその要素にアクセスまたは削除した後のアクションの前に発生します。

そうです、オブジェクトをキューに格納する前に設定された配列の値を確認することが保証されています。(ここでキューに格納された後、配列を一度変更しないことを前提としています)。

于 2013-02-03T20:39:58.993 に答える
1

オブジェクトの構築後、最終的なフィールドが表示され、正しいことが保証されます。注: これは、それらのフィールドが参照するオブジェクトには適用されません。つまり、byte[] は一貫していない可能性があります (ただし、ほとんどの JVM では一貫していると思われます)

ExecutorService を使用する簡単な解決策があります。キューとスレッド プールをラップするだけでなく、揮発性フィールドに十分なアクセスを行い、データが正しいことを確認します。

要するに、シンプルに保ち、標準ライブラリを使用すると、機能する可能性が高くなります。

于 2013-02-03T20:44:00.933 に答える