問題タブ [double-checked-locking]
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.
c++ - ダブルチェックロックでの競合状態の説明
スレッドが別のスレッドによって書き込まれたポインターを認識した場合、新しく作成されたsome_resourceのインスタンスを認識できず、do_something()の呼び出しが誤った値で動作する可能性があります。これは、C ++標準によってデータ競合として定義され、未定義動作として指定された競合状態のタイプの例です。
質問>競合状態を引き起こすダブルチェックロックの問題がコードにある理由について、上記の説明を見ました。しかし、私はまだ問題が何であるかを理解するのに苦労しています。たぶん、具体的な2スレッドのステップバイステップのワークフローは、上記のコードの競合の問題を本当に理解するのに役立ちます。
この本で言及されている解決策の1つは次のとおりです。
コメントは大歓迎です-ありがとう
java - なぜ同期ブロックでvolatileを使用するのですか?
変数が元々揮発性であると宣言されている間に、コードのブロックで同期を行って変数を変更するJavaの例をいくつか見ました。一意のインスタンスを揮発性として宣言し、ブロックを同期したシングルトンクラスの例で見ました。それはそのインスタンスを初期化します...私の質問は、同期中にそれを揮発性と宣言する理由、なぜ両方を行う必要があるのかということです。それらの1つは他のために十分ではありませんか?
前もって感謝します。
java - 同期前にメモリを更新しますか?
Javaメモリモデルでは、次のように記述されています。関連するモニターの解放の一部としてスレッドが同期ブロックを終了する場合、JMMはローカルプロセッサキャッシュをメインメモリにフラッシュすることを要求します。同様に、同期ブロックに入るときにモニターを取得する一環として、ローカルキャッシュが無効化されるため、後続の読み取りはローカルキャッシュではなく、メインメモリに直接送信されます。
では、なぜそのコードでインスタンスを揮発性として宣言する必要があるのでしょうか。2番目のスレッドが同期ブロックに入ると、メインメモリに直接移動するからです。
つまり、別のスレッドが同期ブロックに入り、2番目のチェックを行うと、前述のようにメインメモリから更新されることになっています。
c# - シングルトン ダブルチェック同時実行の問題
これとウェブ上の他の記事を読んだ後でも、最初のスレッドがロックに入った後、null を返す方法をまだ理解していません。それを理解している人は、私を助けて、より人間的な方法で説明してもらえますか?
「次のコードを考えてみてください。
上記のコードを考えると、Foo インスタンスを初期化する書き込みは、インスタンス値の書き込みまで遅延する可能性があるため、インスタンスが初期化された状態でオブジェクトを返す可能性が生じます。
これを回避するには、インスタンス値を volatile にする必要があります。"
java - ロックの再確認-落とし穴?
私は約1か月間Javaを使用していますが、それでも一般的にプログラミングのアマチュアです。何か問題が発生した場合は、遠慮なく修正してください。多分私はいくつかの余分な詳細を提供しますが、私は今とても混乱しているので、もう何が重要かを決めることができません。
それで、私はマルチスレッドのクライアントサーバーアプリケーションを開発してきました。すべてのスレッドは同じオブジェクトを使用しており、特定の構成値と共有ロガーが格納されています。このオブジェクトはサーバースレッドで初期化され、引数としてクライアントスレッドクラスコンストラクターに渡されます。最初は、サーバーの起動時にそのオブジェクトのフィールドが1回だけ変更されると想定されていたため、同時アクセスについて心配する必要はありませんでしたが、変更時に一部の構成値を構成ファイルから再読み取りする必要があります。サーバーを再起動します。
いくつかの調査の後で頭に浮かんだ最初のアイデアは、クラスからのいくつかの値が要求されたときに呼び出され、最後のアクセス以降に構成ファイルが変更された場合はそれらの値を再読み取りし、そうでない場合はすぐに戻る同期メソッドを作成することでした。これ:
(上記のコードはテストされていません。一般的な考え方を理解したいだけです)。
しかし、値が要求されるたびにブロックするというアイデアは好きではありませんでした。それは高価に思えるので、私のアプリケーションは将来、大量のスレッドでかなり高負荷になる可能性があります。したがって、私は「良い」アイデアを思いつきました。ロックする前にファイルが変更されているかどうかを確認してから、ロックされたメソッド内で再度チェックし、可能な限りロックを回避することです。
10分後、それがダブルチェックロックと呼ばれることを学び、さらに10分後、この記事を読んだ後、私の世界は2回崩壊しました。 /floatタイプはアトミックではありません。それとも、オブジェクトの作成が含まれないので、結局は機能しますか?また、longでの操作は非アトミックであるため、「lastModified」を揮発性として宣言するだけで本当に十分でしょうか。可能であれば、なぜそれが機能する/機能しないのかについて適切な説明をしたいと思います。前もって感謝します。
PS:同様の質問がすでに数回回答されていることは知っています。「ReReadConfig」ではなく、「getValue」メソッド全体をニッチピッキングして同期するのをやめたほうがいいかもしれませんが、スレッドセーフプログラミングと将来同様のことを避けるために、自分のコードに落とし穴を見つけるため。また、文法やスペルの間違いの可能性についてもお詫びします。英語はあまりよくわかりません。
編集:最初に、最後の「if」句のタイプミスを修正しました。2番目-警告、上記のコードはスレッドセーフではありません。使用しないでください!方法で
if-checkと値が返されるまでの期間にファイルが更新された場合、スレッドAが値を返し始める前にスレッドBがReReadConfigを開始する可能性があり、必要なデータに危険な部分的な変更が発生します。過度のブロッキングなしで必要なことを行う正しい方法は、ReentrantReadWriteLockを使用することですが、それでも、過度の(そして高価なファイルは大きなXMLであると想定される)構成の再読み取りを回避するためにダブルチェックを使用したいと思います。
今では少なくともスレッドセーフに見えますが、チェックするときに揮発性の「lastModified」変数に応じて質問が開いたままになります。揮発性変数は非アトミック操作で何も保証できないことをどこかで読んだことがあります。書き込みは非アトミックです。
java - ダブルチェック ロックの順不同書き込み
二重チェックされたロックのシナリオでの順不同の書き込みについて言及されている例 (参照: IBM の記事とウィキペディアの記事)
コンストラクターが完全に初期化される前に Thread1 が同期ブロックから出てくる単純な理由を理解できませんでした。私の理解によると、「新規」の作成と呼び出しコンストラクターは順番に実行する必要があり、同期ロックはすべての作業が完了するまで解放されるべきではありません。
ここで何が欠けているか教えてください。
java - ダブルロックを使用しているときにシングルトンインスタンスを揮発性にするポイントは何ですか?
同期にダブル ロック メソッドを使用する場合のシングルトンで、単一インスタンスが volatile として宣言されるのはなぜですか? volatile として宣言せずに同じ機能を実現できますか?
java - ダブルチェックロックに対するJava同期効果?
Double-checked locking: Clever, but breakedなどのさまざまな記事を読み、次のコードがマルチスレッドの使用で壊れている理由を理解しました。
ただし、その説明によると、スレッドが同期ブロックを終了すると、書き込みバリアが実行されます。ロックを解放する前に、そのブロックで変更されたすべての変数をメイン メモリにフラッシュする必要があります。したがって、スレッド A が同期ブロックに実行されると、次のプロセスが順番に実行されます。
- 新しい Resource オブジェクトのメモリが割り当てられます。
- Resource のコンストラクタが呼び出され、
- 新しいオブジェクトのメンバー フィールドを初期化します。
- SomeClass のフィールド リソースには、新しく作成されたオブジェクトへの参照が割り当てられます。
最後に、スレッド A が同期ブロックから出る前に、スレッド A はそのローカル リソース オブジェクトをメイン メモリに書き戻し、スレッド B は、同期ブロックに到達すると、この新しく作成されたリソースをメイン メモリから読み取ります。
スレッド B がこれらのメモリ操作を、スレッド A が実行する順序とは異なる順序で見ることができるのはなぜですか? スレッド B は、共有可能なメイン メモリからしかリソース オブジェクトを読み取ることができないため、スレッド A が同期ブロックから出るときにローカル メモリをメイン メモリにフラッシュするまで、リソース オブジェクトが作成されたことをスレッド B は認識しないと思いましたか?
私の理解を修正してください....ありがとうございます。
c++ - これは、スレッドセーフな Double-Checked Locking パターンを引き換えますか?
元のDouble-Checked Lockingパターンの問題は十分に文書化されています: C++ and the Perils of Double-Checked Locking。SOに関する質問でこのトピックがかなり頻繁に出てくるのを見てきました。
元のパターンの競合状態の問題を解決しているように見えるバージョンを思いつきましたが、問題ないように見えますか?
以下のコードでは、LOCK が適切に実装されたミューテックス型であり、ロック/ロック解除時にメモリ バリアを引き起こすと想定しています。また、パターンの一部ではないため、インスタンスの割り当て解除を処理しようとはしません。
シングルトンを実行する他の可能な方法を認識していますが、それは私が求めているものではありません。私は具体的にパターンについて質問しています - ミューテックスロックの外側に割り当てを行うことで競合状態は解決されますか?.
c++ - C++11: 遅延初期化のための安全なダブル チェック ロック。可能?
スレッドセーフな二重チェック ロック (シングルトンまたは遅延初期化の場合) に関する多くの質問を読みました。一部のスレッドでは、答えはパターンが完全に壊れているというものであり、他のスレッドでは解決策を提案しています。
だから私の質問は: C++ で完全にスレッド セーフな二重チェック ロック パターンを記述する方法はありますか? もしそうなら、それはどのように見えますか。
それが物事をより簡単にするならば、C++11を仮定することができます。私の知る限り、C++11 はメモリ モデルを改善し、必要な改善をもたらすことができました。
ダブルチェックで保護された変数を揮発性にすることで、Javaでそれが可能であることを私は知っています。C++11 はメモリ モデルの大部分を Java のものから借りてきたので、それは可能だと思いますが、どうすればよいでしょうか?