マルチスレッド環境では、データの破損を防ぐためにコードの重要なセクションが確実に保護されることが重要です。そのような重要なセクションの 1 つは、データ キューの管理です。キューは、「先入れ先出し」(FIFO) の原則に従ったデータ構造です。 C 11 でスレッドセーフ キューを実装するには、ミューテックスや条件変数などの同期メカニズムを使用する必要があります。
問題のコード スニペットは、std::mutex と std::condition_variable を使用してスレッドセーフ キューを示しています。 enqueue メソッドは、キューを保護するために qMutex のロックを保持しながら項目をキューに追加します。また、populatedNotifier 条件変数を使用して、待機中のスレッドに通知します。
デキュー メソッドは、キューから項目を取得します。 qMutex 上で一意のロックを取得し、キューが空かどうかを確認し、必要に応じてタイムアウト付きの wait_for 関数を使用して待機します。スレッドがキュー内の新しいアイテムを通知されると、スレッドは待機を終了し、キューからアイテムを取得して削除します。
ただし、キューが空のときにセグメンテーション違反が観察され、wait_for 関数が返されたことが示されます。通知なしで。これは、偽のウェイクアップが原因で発生する可能性があります。
この問題を回避するには、while ループの条件を反転することをお勧めします。 「キューが空にならないまで待つ」のではなく、「キューが空になるまで」待ちます。これにより、偽のウェイクアップ後にループがキューの空性を再チェックすることが保証されます。
デキュー メソッドの改訂版は次のとおりです。
<code class="cpp">std::string FileQueue::dequeue(const std::chrono::milliseconds& timeout) { std::unique_lock<std::mutex> lock(qMutex); while (q.empty()) { if (populatedNotifier.wait_for(lock, timeout) == std::cv_status::no_timeout) { // Lock may have been released spuriously; recheck condition if (q.empty()) { return std::string(); } std::string ret = q.front(); q.pop(); return ret; } else { return std::string(); } } std::string ret = q.front(); q.pop(); return ret; }</code>
これにより、次の場合にのみスレッドが続行されることが保証されます。キューは空ではないため、偽のウェイクアップによって引き起こされるセグメンテーション違反が回避されます。
以上が`std::condition_variable::wait_for` を使用するときに C 11 スレッドセーフ キューでのセグメンテーション違反を防ぐ方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。