問題タブ [happens-before]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - 揮発性フィールドと非揮発性フィールドが混在する場合の揮発性先行発生関係
揮発性フィールドと非揮発性フィールドが混在している場合の揮発性フィールドの事前発生動作を理解しようとしています。
1 つの WriteThread と 5 つの ReadThreads があり、SharedObject を更新/読み取るとします。
ReadThreadswaitToBeStopped()
は最初からメソッドを呼び出し、WriteThread はstop()
1 秒後にメソッドを呼び出します。
このプログラムが終了すると、出力は次のようになります。100 以上の ReadThreads を試しても、結果は常に同じです。
Q1. これが常に1,2,3,0,0,0ではなく4,5,6,7,8,9を返す理由を誰かが説明できますか?
事前発生関係についての私の理解は、次のようなものでした。
- WriteThread の書き込みは、WriteThread の書き込みの
a=1,b=2,c=3
前に発生します。stopRequested
- WriteThread の書き込みは、WriteThread の書き込みの
stopRequested
前に発生します。a=4,b=5,c=6,d=7,e=8,f=9
- WriteThread の書き込みは、ReadThread の読み取りの
stopRequested
前に発生しますstopRequested
- ReadThread 読み取りは、 ReadThread 読み取りの
stopRequested
前に発生しますa,b,c,d,e,f
これらの 4 つのステートメントから、このようなステートメントを導き出すことはできません...
- WriteThread の書き込みは、ReadThread の読み取りの
a=4,b=5,c=6,d=7,e=8,f=9
前に発生しますa,b,c,d,e,f
役立つ場合は、コードの他の部分を次に示します。
java - HashMap と ConcurrentHashMap: スレッド間の転送
マルチスレッド アプリケーションでのマップの使用について質問があります。次のようなシナリオがあるとします。
List<Map<String, Object>>
スレッドは、Jackson Json によって逆シリアル化されたjson データを受け取ります。- このスレッドは、受信したマップを変更します。
- 次に、別のスレッドによって消費されるように、リストをブロッキング キューに入れます。
ご覧のとおり、マップは単一のスレッドによってのみ変更されますが、読み取り専用になり (何も変更されず、変更されなくなります)、別のスレッドに渡されます。HasMap
次に、 (もTreeMap
) との実装を調べたところConcurrentHashMap
、後者にはvolatile
フィールドがありますが、最初の 2 つにはありません。では、この場合、どの実装Map
を使用すればよいでしょうか? ConcurrentHashMap
過剰な選択ですか、それともスレッド間転送のために使用する必要がありますか?
私の簡単なテストではHashMap/TreeMap
、それらが同期的に変更され、機能する場合に使用できることが示されていますが、私の結論またはテスト コードが間違っている可能性があります。
メイン スレッドは、共通マップを同期的に更新する 5 つの子スレッドを生成します。メイン スレッドが完了すると、子スレッドによるすべての更新が正常に表示されます。
java - JVM は、Happens-Before を使用して、フィールドに値を直接割り当てずに、すべてのスレッドのフィールドの値を更新しますか?
別のスレッドから非揮発性フィールドに書き込むと、おそらくそれをキャッシュできるので、他のすべてのスレッドが実際の値を認識しないことはすでにわかっています。しかし、たとえばstart()
、割り当て値をフィールドに割り当てた後にスレッドオブジェクトで呼び出すと、JVM は他のすべてのスレッドのこの値を更新します。しかし、同じアクションを実行する場合、JVM はこのフィールドの値を更新しますが、次のようにフィールドに直接ではなくobject.field = 100
メソッドを呼び出して値を割り当てますobject.setFiled(100)
。
この場合、フィールドの値は他のすべてのスレッドで確実に同じになります
しかし、この場合、結果は同じでしょうか?