現在、C++でのマルチスレッドに関する書籍を読んでいます。ある章では、スレッドセーフなキューのソースコードをいくつか見つけました。それは、おおよそ次のように構築されています:値をキューにプッシュされている場合スレッドセーフキューと疑似ウェイク
template<typename T>
class QueueThreadSafe
{
private:
std::mutex m_mutex;
std::queue<T> m_dataQueue;
std::condition_variable m_dataCondition;
public:
void push(T someValue)
{
std::lock_guard<std::mutex> guard(m_mutex);
m_dataQueue.push(someValue);
m_dataCondition.notify_one();
}
void pop(T &retVal)
{
std::unique_lock<std::mutex> lock(m_mutex);
m_dataCondition.wait(lock, [this]{return !m_dataQueue.empty();});
retVal = m_dataQueue.front();
m_dataQueue.pop();
}
};
、データ条件が通知され、いくつかの(可能な)ポップでスレッドを待って作業を再開することができます。このシナリオで私が混乱しているのは、偽の目覚めです。同時に1つのスレッドに通知され、別のスレッドが同時に起動するとどうなりますか?もちろん、彼は空でないキューも見ています。このシナリオでは、2つの異なるスレッドが値をポップしようとしますが、おそらくは値が1つしかありません - 古典的な競合状態です。
ここで何か不足していますか?これを行うより良い方法はありますか?
@ 1201ProgramAlarm:[条件変数の既知の動作](https://en.wikipedia.org/wiki/Spurious_wakeup)です。それらを最適化するために使用された戦略は、偶発的なウェークアップ信号に対して脆弱になり、プログラムロジックは、条件が満たされない場合に覚醒してスリープした後の状態を再チェックすることによってそれを処理する必要があります。 – ShadowRanger
コメント - 一部のオペレーティングシステムでは、Windows [WaitForMultipleObjects()](https://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(英語))など、複数のオブジェクトを待機する汎用の「アトミック」機能があります。 v = vs.85).aspx)。キューの場合、2つのオブジェクトはミューテックスとセマフォである可能性があります。セマフォ "count"は、キュー内の要素の数を反映します。競争条件と偽の目覚ましは問題ではありません。 – rcgldr
ミューテックスとセマフォに使用される[WaitForMultipleObjects()](https://msdn.microsoft.com/en-us/library/windows/desktop/ms687025(v = vs.85).aspx)の場合、関数はmutexとゼロ以外のセマフォ "count"の両方を待機し、呼び出し元に戻る前に非ゼロセマフォ "count"をデクリメントします。これは競争条件を排除するものの一部です。 – rcgldr