バージョン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を使用するだけです) )。しかし、それが何のためにあるのか私には分かりません。
plain -> opaque -> release/acquire -> volatile (sequential consistency)
。