Javaで使用されるメモリフェンスとは何ですか?
バージョン9でJava SEに追加された新しいクラスSubmissionPublisher(Java SE 10のソースコード、OpenJDK | docs)がどのように実装されているかを理解しようとしているVarHandleときに、以前は知らなかったいくつかのAPI呼び出しに遭遇しました。 fullFence、acquireFence、releaseFence、loadLoadFenceとstoreStoreFence。 特にメモリバリア/フェンスの概念に関していくつかの調査を行った後(以前に聞いたことがありますが、使用していなかったため、セマンティクスにはまったく不慣れでした)、それらの目的について基本的な理解ができたと思います。それにもかかわらず、私の質問は誤解から生じる可能性があるため、私はそもそもそれが正しく行われたことを確認したいと思います。 メモリバリアは、読み取りおよび書き込み操作に関する制約を並べ替えています。 メモリバリアは、読み取りまたは書き込み、あるいはその両方に制約を設定するかどうかに応じて、単方向および双方向のメモリバリアという2つの主要なカテゴリに分類できます。 C ++はさまざまなメモリバリアをサポートしていますが、これらはが提供するバリアとは一致しませんVarHandle。ただし、で利用可能なメモリバリアの一部は、対応するC ++メモリバリアと互換性のある順序付け効果をVarHandle提供します。 #fullFence と互換性があります atomic_thread_fence(memory_order_seq_cst) #acquireFence と互換性があります atomic_thread_fence(memory_order_acquire) #releaseFence と互換性があります atomic_thread_fence(memory_order_release) #loadLoadFenceそして、#storeStoreFence互換性のあるC ++カウンターパートを持っていません 詳細に関してはセマンティクスが明らかに異なるため、ここでは互換性という言葉は本当に重要なようです。たとえば、すべてのC ++バリアは双方向ですが、Javaのバリアはそうではありません(必須)。 ほとんどのメモリバリアにも同期効果があります。これらは特に、使用されているバリアタイプと、他のスレッドで以前に実行されたバリア命令に依存します。バリア命令が持つ完全な影響はハードウェア固有なので、高レベル(C ++)のバリアを使用します。たとえば、C ++では、バリア解放命令の前に行われた変更は、バリア取得命令を実行するスレッドに表示されます。 私の仮定は正しいですか?もしそうなら、私の結果の質問は: で使用可能なメモリバリアはVarHandle、何らかの種類のメモリ同期を引き起こしますか? それらがメモリ同期を引き起こすかどうかに関係なく、Javaで何を並べ替える制約が役立つのでしょうか?Javaメモリモデルは、揮発性フィールド、ロック、またはVarHandle操作など#compareAndSetが関係する場合の順序付けに関して、すでにいくつかの非常に強力な保証を提供しています。 例を探している場合:前述BufferedSubscriptionのSubmissionPublisher(上記のリンクされたソース)の内部クラスは、1079行に完全なフェンスを設定しました(関数growAndAdd;リンクされたWebサイトはフラグメント識別子をサポートしていないため、CTRL + Fを使用するだけです) )。しかし、それが何のためにあるのか私には分かりません。