古典的な生産者消費者問題で。プロデューサーは、 itemCount == BUFFER_SIZE
AMD がダウンしたときに再びウェイクアップするとスリープします。しかし、いったんitemCount
大きくなると、プロデューサー スレッドはスリープ状態になります。それがダウンしたことをどのように知ることができ、itemCount
ダウンする必要があるのwakeup
でしょうか?
3 に答える
疑似コードでは、プロデューサーは次のようなものです。
void producer_thread()
{
while(true)
queue.push( produce() );
}
そのため、キュー プッシュ メソッドを検討してください (ここでは pthreads を使用しましたが、他のライブラリにも同じロジックが適用されます)。
void SynchronizedQueue::push(Item const &i)
{
pthread_mutex_lock(&mutex);
// queue is full, so wait for consumer
while (queue.size() == BUFFER_SIZE)
pthread_cond_wait(&condition, &mutex);
// when we get here, the queue has space
this->queue.push_back(i);
// make sure we wake a sleeping consumer
if (queue.size() == 1)
pthread_cond_signal(&condition);
pthread_mutex_unlock(&mutex);
}
コンシューマーが使用する pop メソッド:
Item SynchronizedQueue::pop()
{
pthread_mutex_lock(&mutex);
// wait for something to do
while (queue.size() == 0)
pthread_cond_wait(&condition, &mutex);
// if we get here, we have some work
Item tmp = queue.front();
// make sure we wake a sleeping producer
if (queue.size() == BUFFER_SIZE)
pthread_cond_signal(&condition)
queue.pop_front();
pthread_mutex_unlock(&mutex);
return tmp;
}
条件変数が必要です。
条件変数の一般的な使用法は次のとおりです。
//lock the mutex first!
scoped_lock myLock(myMutex);
//wait till a condition is met
myConditionalVariable.wait(myLock, CheckCondition);
//Execute this code only if the condition is met
whereCheckCondition
は、条件をチェックする関数 (またはファンクター) です (たとえば、いつ目を覚ますかなど)。疑似wait()
的にウェイクアップしたときに関数によって内部的に呼び出され、条件がまだ満たされていない場合、関数は再びスリープします。スリープに入る前に、mutex をアトミックに解放します。wait()
wait()
お使いのコンパイラstd::conditional
が C++11 で導入されたサポートをサポートしている場合、詳細については次を参照してください。
コンパイラがそれをサポートしておらず、win32 スレッドで作業している場合は、次を参照してください。
そして、これが完全な例です。
また、POSIX スレッドを使用する場合は、次を参照してください。
conditional_variable
ここで、win32 プリミティブを使用する私の実装を確認できます。
下にスクロールして、最初にその実装を確認してから、同時キューの実装での使用法を確認してください。
知る必要はありません-消費者が信号を送ると、OSはそれをウェイクアップします。PCキューコードでは、プロデューサーはOS同期プリミティブでwait()呼び出しを行います。この呼び出しは、コンシューマースレッドがスペースを作成してOSシンクロオブジェクトに信号を送るまで戻りません(障害のあるOSが「スプリアスウェイクアップ」をサポートしている場合を除く)。その時点で、待機中のプロデューサースレッドが準備され、使用可能なコアがある場合は、すぐに実行します-wait()呼び出しが返されます。
従来、PCキューは、単純な非スレッドセーフキュー、インデックス/ポインターを保護するミューテックス、および2つのセマフォから構築されます。1つはキュー内のアイテムをカウントするために0に初期化され、もう1つは空のスペースをカウントするために[キューサイズ]に初期化されます。 。プロデューサーは「emptySpace」を待機し、シグナルを取得すると、ミューテックスをロックし、オブジェクトをエンキューし、ミューテックスをロックして「itemCount」をシグナルします。コンシューマーは「itemCount」を待機し、シグナルを取得すると、ミューテックスをロックし、オブジェクトをデキューし、ミューテックスをロックして「emptySpace」にシグナルを送信します。