問題タブ [java-memory-model]
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 - Javaオブジェクト構造のスレッドセーフ公開?
次のコードがあると仮定します。
「Catalog」はオブジェクト構造であり、メソッド createCatalog() と「Catalog」オブジェクト構造は並行性を考慮して作成されていません。製品カタログ内にはいくつかの非最終的で揮発性のない参照があり、変更可能な状態さえあるかもしれません (ただし、これは処理する必要があります)。
私がメモリモデルを理解している方法では、このコードはスレッドセーフではありません。安全にする簡単な方法はありますか?(この問題の一般化されたバージョンは、実際には、スレッドが爆発的に動作する前に作成される共有構造のシングルスレッド構築に関するものです)
java - Java での同期のメモリ効果
JSR-133 FAQは次のように述べています。
しかし、同期には相互排除以上のものがあります。同期により、同期ブロックの前または最中のスレッドによるメモリ書き込みが、同じモニターで同期する他のスレッドに予測可能な方法で表示されるようになります。同期ブロックを終了した後、モニターを解放します。これにより、キャッシュがメイン メモリにフラッシュされ、このスレッドによって行われた書き込みが他のスレッドから見えるようになります。同期ブロックに入る前に、モニターを取得します。これにより、ローカル プロセッサのキャッシュが無効になり、変数がメイン メモリから再ロードされます。その後、以前のリリースで可視化されたすべての書き込みを確認できます。
また、最新の Sun VM では、非競合同期は低コストであるという記事を読んだことも覚えています。私はこの主張に少し混乱しています。次のようなコードを検討してください。
x への更新には同期が必要ですが、ロックを取得すると y の値もキャッシュからクリアされますか? もしそれが本当なら、ロックストライピングのような技術は役に立たないかもしれないからです。あるいは、JVM はコードを確実に分析して、同じロックを使用して別の同期ブロックで y が変更されていないことを確認し、同期ブロックに入るときに y の値をキャッシュにダンプしないようにすることはできますか?
java - イベントディスパッチスレッドはJavaメモリモデルに適合しています
これは、私が以前に尋ねた質問に関連しています。答えは次のとおりです。
フィールドが複数のスレッドによってアクセスされる場合、そのフィールドは揮発性または最終的であるか、同期されたブロックでのみアクセスされる必要があります。そうしないと、割り当てられた値が他のスレッドに表示されない場合があります。
さらに、画面上のピクセルを操作するものはすべて、イベントディスパッチスレッドから実行する必要がありますが、これはrepaint/paintを使用すると透過的に処理されます。
したがって、私の理解では、画面上を移動するスプライトのアニメーションのような単純なもののメモリモデルについて心配する必要があります。
私の質問は、この理解は正しく、Sunのチュートリアルの例( TumbleItem(ソース)など)は正しくないかということです。
java - Java 同時実行に関する質問 - コレクションでの同期
同期化された次のコード スニペットはArrayList
、マルチスレッド環境で機能しますか?
あるスレッドが別のスレッドによる変更を確認できないことが心配です。
java - コンウェイのライフ ゲームのマルチスレッド Java プログラム - 境界セルでの競合
Java で並行プログラミングを学んでいて、Game of Life のシミュレーションを書いています。
これが私が考えていることです:
- int[][] を使用してセルの状態を保存します
- int[][] を t 個のセグメントに分割し、t 個のワーカー スレッドを使用する
- t スレッドはセグメントから読み取り、セグメント内のすべてのセルの新しい値を計算し、セルを更新します。
- 計算が終了すると、障壁で他のワーカーが終了するのを待ちます
- バリアを越えると、メイン スレッドが UI を更新します。
- ワーカーは次の状態の計算に進みます。
現在、セグメントの共通の境界で競合が発生しています。隣接セルが前の値を読み取る前にスレッドが境界セルの状態を上書きした場合、隣接セルの計算は間違っています。
私のオプションは何ですか?
- runnable の代わりに callable を使用し、ワーカー スレッドが新しい値を返すようにします (セグメント自体を更新するのではなく)。バリアを越えた後、メイン スレッドはマトリックスを更新できます。このオプションでは、ワーカー スレッドによって返された結果をマトリックスにコピーします。
- 2 つのバリアを使用します。ワーカー スレッドは、隣接するセグメントから境界セルのコピーを作成し、最初のバリアで待機します。このバリアを通過すると、次の状態の計算に進み、その場でセグメントを更新します。その後、2 番目のバリアで待機します。メイン スレッドが UI を更新します。
私の質問は、データのコピーを伴わない、または上記の 2 つのオプションよりも効率的な境界セルでの競合に対処する他の方法はありますか? ReaderWriterLock、揮発性変数、またはその他の同期メカニズムを使用している可能性がありますか?
更新: これまでのところ、Peter によるダブル バッファリング ソリューションが最もクリーンなソリューションです。しかし、質問があります。2 つの配列は共有データであり、同期 (同期アクセスまたは揮発性変数) を使用していないため、可視性の問題は発生しませんか? 複数の CPU が配列の値をキャッシュし、各反復で配列の一部のみを更新できますか? 次に、スレッドは境界セルの古い値を取得します。これは可能ですか?そうでない場合は、その理由。はいの場合、どうすれば解決できますか? 2 つの配列を volatileと宣言しても、個々の要素が volatile にならないようです。
java - 揮発性の保証とアウトオブオーダー実行
重要な編集2つの割り当てが行われているスレッドの「前に起こる」について知っています。私の質問は、 「a」がまだnullである間に、別のスレッドが「b」をnull以外で読み取る可能性があるかどうかです。したがって、以前にsetBothNonNull(...)を呼び出したスレッドと同じスレッドからdoIt()を呼び出している場合、NullPointerExceptionをスローすることはできません。しかし、setBothNonNull(...)を呼び出すスレッドとは別のスレッドからdoIt()を呼び出す場合はどうなるでしょうか。
この質問はvolatile
キーワードとvolatile
保証に関するものであることに注意してください。キーワードに関するものではありません(したがって、解決する問題がないため、「同期を使用する必要があります」と答えないでください。単に保証synchronized
を理解したいだけです。volatile
(または保証の欠如)アウトオブオーダー実行に関して)。
volatile
コンストラクターによってnullに初期化される2つの文字列参照を含むオブジェクトがあり、2つの文字列を変更する方法は1つしかないとします。つまり、 setBoth(...)を呼び出し、後でそれらの参照を非に設定することしかできません。 null参照(コンストラクターのみがそれらをnullに設定できます)。
たとえば(これは単なる例であり、まだ質問はありません):
setBothNoNull(...)では、非nullパラメータ「a」を割り当てる行が非nullパラメータ「b」を割り当てる行の前に表示されます。
次に、これを行うと(もう一度、質問はありません。質問は次に来ます):
アウトオブオーダー実行のためにNullPointerExceptionが発生する可能性があることを理解していますか?
言い換えると、null以外の「b」を読み取ったためにnull以外の「a」を読み取るという保証はありませんか?
アウトオブオーダー(マルチ)プロセッサとvolatile
動作方法により、「a」の前に「b」を割り当てることができますか?
volatile
書き込みに続く読み取りは常に最後に書き込まれた値を参照することを保証しますが、ここには順序が正しくない「問題」がありますか?volatile
(繰り返しになりますが、「問題」は、問題を解決するためではなく、キーワードとJavaメモリモデルのセマンティクスを理解しようとすることを目的としています)。
scala - Scala と Java メモリ モデル
Java メモリ モデル (1.5 以降) は、フィールドfinal
を非final
フィールドとは異なる方法で扱います。特に、this
構築中に参照がエスケープされない限りfinal
、コンストラクターのフィールドへの書き込みは、オブジェクトがデータ競合を介して他のスレッドで使用可能になった場合でも、他のスレッドで可視であることが保証されます。(非フィールドへの書き込みfinal
は表示されるとは限らないため、それらを不適切に公開すると、別のスレッドがそれらを部分的に構築された状態で見る可能性があります。)
Scalaコンパイラがクラスのバッキングフィールドをfinal
(非ではなく)作成する方法/場合に関するドキュメントはありますか? final
言語仕様に目を通し、Web を検索しましたが、決定的な答えが見つかりません。(比較すると、@scala.volatile
注釈はフィールドを としてマークするように文書化されていますvolatile
)
java - Java LockSupport メモリの一貫性
Java 6 API の質問です。呼び出しLockSupport.unpark(thread)
は、パーク解除されたばかりのスレッドからの戻りに対して発生前の関係を持っていますか? LockSupport.park
答えはイエスだと強く思いますが、Javadoc には明示的に言及されていないようです。
java - CopyOnWriteArrayList をスレッドセーフにするにはどうすればよいですか?
のOpenJDK ソース コードを調べたCopyOnWriteArrayList
ところ、すべての書き込み操作は同じロックで保護されており、読み取り操作はまったく保護されていないようです。私が理解しているように、JMM では、変数へのすべてのアクセス (読み取りと書き込みの両方) をロックで保護する必要があります。そうしないと、並べ替え効果が発生する可能性があります。
たとえば、set(int, E)
メソッドには次の行が含まれています (ロックされています)。
一方get(int)
、メソッドはreturn get(getArray(), index);
.
JMM についての私の理解では、これは、get
ステートメント 1 ~ 4 が 1-2(new)-4-2(copyOf)-3 のように並べ替えられると、配列が矛盾した状態になる可能性があることを意味します。
CopyOnWriteArrayList
JMM の理解が間違っているのでしょうか、それともスレッドセーフである理由について他に何か説明はありますか?
java - 二項係数の成長可能な配列のダブルチェックロック
二項係数の配列を維持するためにダブルチェック ロックを使用しようとしていますが、ダブルチェック ロックが機能しないことを最近読みました。効率は非常に重要であるため、条件ステートメント内でのみ使用しない限り、volatile を使用することはできません。シングルトンオブジェクトで静的クラスを使用する方法がわかりません(これはフレームワークの一部であり、関数を使用する必要がある数値の種類がわからないため、最大値を推測できません選択された値は、または関数がまったく使用されるかどうか)。私が考えることができる唯一のことは、すべてを静的ではなく、このメソッドを使用する必要がある各スレッドが独自の配列で Choose オブジェクトをインスタンス化することを主張することです。それは必要ではないようです。