(2つの質問につながる質問)
C++ 11 では、2 つのスレッドが同時にロックを取得できないことを確実に保証できるという点で、ロックはアトミックですか?
上記の答えが「はい」の場合、ダブルチェック ロックの目的は何ですか?
最後に、アトミック プリミティブ (明らかに、 atomicであることがわかっています) を使用し、ロックが取得されたかどうかに応じてこれを 1 または 0 に設定できるのに、なぜ std::lock() が必要なのですか?
(2つの質問につながる質問)
C++ 11 では、2 つのスレッドが同時にロックを取得できないことを確実に保証できるという点で、ロックはアトミックですか?
上記の答えが「はい」の場合、ダブルチェック ロックの目的は何ですか?
最後に、アトミック プリミティブ (明らかに、 atomicであることがわかっています) を使用し、ロックが取得されたかどうかに応じてこれを 1 または 0 に設定できるのに、なぜ std::lock() が必要なのですか?
ダブルチェック ロックの背後にある混乱した考えは、状態をチェックするときにロックを取得せず、ありそうもない状態でのみロックを取得することです。ただし、これを機能させるには、かなりの量の同期が必要ですが、これはかなり間違いやすいものです。ダブルチェック ロックの主な用途は、シングルトン (それ自体は悪い考えです) とスレッド間で共有される定数オブジェクトの初期化であるため、C++11 は関数ローカルstatic
オブジェクトのスレッド セーフな初期化を実際に実装しています。これにより、人々が二重チェックのロックを正しく取得しようとするケースの大部分が取り除かれます。
それ以外: ミューテックス ロックのポイントは、多くても 1 つのスレッドがミューテックス ロックを取得できることです。つまり、2 つのスレッドが同じロックを取得できないことが保証されます。アトミック変数を使用してロックに似たものを示すことに関しては、ミューテックスのロック/ロック解除は、アトミック値を変更することによって行われるものを超えて追加の同期を追加することに注意する必要があります: スレッドが 1 つだけであることを知るだけでは十分ではありません。共有状態を変更する場合、システムに加えられた変更を通知する必要もあります。また、通常のロックは、ロックを取得できない場合にスレッドの実行を一時停止することがあります (ただし、実装で実行する必要はないと思います。つまり、スピン ロックを使用してビジー状態の待機を実行できると思います)。
誰かがロックを取得している間にロックを破壊するなどの巧妙なことをしようとしない限り、ロックは 100% アトミックです。
ロックには時間がかかります。ロックをチェックする必要があるのはごくわずかな時間だけである場合、二重チェックのロックを使用すると、ロックのコストを回避でき、ロックをスキップしても安全であることを証明できない場合にのみロックする必要があります。
ロックを待機できるため、単純にロックをアトミック プリミティブに置き換えることはできません。ロックを待機すると、OS はそのスレッドの実行を停止し、CPU パワーを別の場所で消費します。アトミック プリミティブをループしていると、CPU がビジー状態になり、有用なことを実行できなくなります。
そうは言っても、そのように構築されたスピンロックと呼ばれるロック構造があり、数サイクルしかロックしないと期待できる場合は非常に高速です。
また、アトミック変数で condition_variables を使用することはできません。実際のロックが必要です