C 11 スレッド セーフ キュー: 条件変数の使用に関する混乱
コード内で、ミューテックスを使用してスレッド セーフ キューを実装しました。そして条件変数。ただし、条件変数によって制御されるコード ブロック内で時折セグメンテーション違反が発生します。具体的には、キューが空の場合にセグメンテーション違反が発生することがわかります。これは、条件変数がキュー内の新しい項目の利用可能性を通知することを目的としているため、直感に反するように見えます。
条件変数の不正な使用
あなたの誤解は、条件変数の誤った使用に起因しています。条件変数の目的は、共有状態の変化を通知し、他のスレッドがこの変化に反応できるようにすることです。ただし、コードでは条件変数を使用して、特定の条件 (キューが空) が false になるのを待機しています。これは正しくありません。条件が false になると (つまり、キューが空でなくなると)、スレッドは起動しますが、条件が false のままであることは保証されません (つまり、その間にキューが再び空になる可能性があります)。 .
条件変数の適切な使用法
条件変数を利用する正しい方法は、条件 (この場合はキューが空かどうか) をチェックするループを作成することです。 ) 条件が満たされない場合は待機状態になります。条件が通知されると、スレッドは起動しますが、続行する前にすぐに条件を再チェックします。これにより、ウェイクアップ時に条件がまだ true である場合にのみ、スレッドが目的の操作を実行することが保証されます。
代替実装
スレッドセーフの代替実装は次のとおりです。この問題に対処するキュー:
<code class="cpp">template <class T> class SafeQueue { public: SafeQueue() : q(), m(), cv() {} void enqueue(T t) { std::lock_guard<std::mutex> lock(m); q.push(t); cv.notify_one(); } T dequeue() { std::unique_lock<std::mutex> lock(m); while (q.empty()) cv.wait(lock); T val = q.front(); q.pop(); return val; } private: std::queue<T> q; mutable std::mutex m; std::condition_variable cv; };</code>
この実装では、条件変数は、キューが空である (または enqueue メソッドの場合は空ではない) 条件が false になるのを待機するために正しく使用されます。スレッドは、ウェイクアップ後にキューが空でない場合にのみ、必要な操作 (アイテムのデキュー) を実行します。
以上がC で条件変数を使用して空のキューをチェックするとセグメンテーション違反が発生するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。