2017-10-19 14 views
0

私はスレッドの2つのグループを持っているとしましょう。 1つのグループの機能は、要素を配列に追加することです。もう1つのグループの機能は、配列に同じ要素が含まれている場合、要素を配列から削除することです。ルールは、スレッドが空であり、待機しなければならない場合、スレッドは配列から要素を削除できないということです。モニターは、この同期の問題を解決するために使用されます。condition_variable wait関数が呼び出されたときにスレッドはどのように待機しますか?

すべてのスレッドが同時に起動し、コンシューマスレッドが最初にミューテックスをロックしてから、配列が空でないか、条件が偽であるかをチェックしてミューテックスのロックを解除するシナリオを考えてみましょう。次に、プロデューサスレッドは最初にミューテックスをロックし、要素を追加し、待機中のすべてのスレッドに通知し、ミューテックスをロック解除します。疑問は、待機スレッドが通知された後、待機中のスレッドがその要素を削除しようとするか、mutexが再び解放され、任意のスレッドが偶然それをロックする可能性があり、待っているスレッドが条件が失敗した後に終了しますが、それがスレッドプールに戻されたとしましょう。

+2

いくつかの(擬似的な)コードを表示したほうがいいですが、あなたが求めていることを理解することは非常に難しいです。 – Slava

答えて

2

まず、(cppreference's page about std::condition_variableの本質を含む)いくつかのことを明確にすることができます:

消費者

消費者は、次の手順を使用してstd::condition_variable -sのwait

  • 獲得をa std::unique_lock<std::mutex>、共有変数を保護するのに使用されているものと同じmutexにある
  • wait、wait_for、またはwait_untilを実行します。待機操作は、ミューテックスを原子的に解放し、スレッドの実行を中断する。
  • 条件変数が通知されると、タイムアウトが満了するか、偽のウェイクアップが発生し、スレッドがアウェイクされ、ミューテックスがアトミックに再取得されます。 スレッドは、ウェイクアップがスプリアスである場合は、条件を確認し、待機を再開する必要があります。

プロデューサ

生産手順以下notify同じstd::condition_variable -s:

  • が修正を行い(典型的にはstd :: lock_guardを介して)はstd :: mutexを獲得ロックが保持されている間
  • notify_oneまたはnotify_allを実行する電子std::condition_variable(ロックが通知のために保持する必要はありません)

回答

それが通知されたと待機中のスレッドを試すことができます最初の後に待機中のスレッドがミューテックスへのアクセスを取得しません要素を削除する

はい、同じ条件で複数のコンシューマが存在する可能性があり、それぞれがすべて1つのオブジェクトを消費する可能性があります。付加的な論理的条件を使用した覚醒の目覚め(消費者の部分の太字を参照)。消費者が目を覚ましたとき、それはすでにロックを獲得した

template< class Predicate > 
void wait(std::unique_lock<std::mutex>& lock, Predicate pred); 

std::condition_variablewait方法でもすでにそれを含み、特定のプロトタイプを持っています!したがって、条件(たとえば、!queue->empty())が満たされれば、安全に消費することができます。

関連する問題