2

古典的な生産者消費者問題で。プロデューサーは、 itemCount == BUFFER_SIZEAMD がダウンしたときに再びウェイクアップするとスリープします。しかし、いったんitemCount大きくなると、プロデューサー スレッドはスリープ状態になります。それがダウンしたことをどのように知ることができ、itemCountダウンする必要があるのwakeupでしょうか?

4

3 に答える 3

2

疑似コードでは、プロデューサーは次のようなものです。

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;
}
于 2012-06-24T18:46:07.870 に答える
1

条件変数が必要です。

条件変数の一般的な使用法は次のとおりです。

//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 プリミティブを使用する私の実装を確認できます。

下にスクロールして、最初にその実装を確認してから、同時キューの実装での使用法を確認してください。

于 2012-06-24T18:36:46.283 に答える
0

知る必要はありません-消費者が信号を送ると、OSはそれをウェイクアップします。PCキューコードでは、プロデューサーはOS同期プリミティブでwait()呼び出しを行います。この呼び出しは、コンシューマースレッドがスペースを作成してOSシンクロオブジェクトに信号を送るまで戻りません(障害のあるOSが「スプリアスウェイクアップ」をサポートしている場合を除く)。その時点で、待機中のプロデューサースレッドが準備され、使用可能なコアがある場合は、すぐに実行します-wait()呼び出しが返されます。

従来、PCキューは、単純な非スレッドセーフキュー、インデックス/ポインターを保護するミューテックス、および2つのセマフォから構築されます。1つはキュー内のアイテムをカウントするために0に初期化され、もう1つは空のスペースをカウントするために[キューサイズ]に初期化されます。 。プロデューサーは「emptySpace」を待機し、シグナルを取得すると、ミューテックスをロックし、オブジェクトをエンキューし、ミューテックスをロックして「itemCount」をシグナルします。コンシューマーは「itemCount」を待機し、シグナルを取得すると、ミューテックスをロックし、オブジェクトをデキューし、ミューテックスをロックして「emptySpace」にシグナルを送信します。

于 2012-06-24T19:51:17.503 に答える