3

これについて: 条件変数の使用方法

そのようなコードを実行するコンシューマースレッドがいくつかあるとします(参照ページからコピー):

while (TRUE) {
    s = pthread_mutex_lock(&mtx);
    while (avail == 0) {   /* Wait for something to consume */
       s = pthread_cond_wait(&cond, &mtx);
    }
    while (avail > 0) {   /* Consume all available units */ 
        avail--;
    }
    s = pthread_mutex_unlock(&mtx);
}

ここでのシナリオは次のとおりです。メインスレッドはpthread_cond_signal()を呼び出して、コンシューマースレッドに何らかの作業を行うように指示します。

私が理解しているように、後続のスレッドはpthread_mutex_lock()を呼び出し、次にpthread_cond_wait()(ミューテックスをアトミックにロック解除します)を呼び出します。今では、どのコンシューマースレッドもミューテックスを要求しておらず、すべてpthread_cond_wait()を待機しています。

メインスレッドがpthread_cond_signal()を呼び出すと、マンページに続いて、少なくとも1つのスレッドがウェイクアップされます。それらのいずれかがpthread_cond_wait()から戻ると、自動的にミューテックスを要求します。

だから私の質問は:提供されたサンプルコードに関して今何が起こっているのですか?つまり、ミューテックスのコンテストに負けたスレッドは今何をしているのでしょうか?

(ミューテックスを獲得したスレッドは、残りのコードを実行してミューテックスを解放する必要があります。失われたスレッドは、ミューテックスを待機している必要があります-最初のネストされた whileループのどこか-勝者がそれを保持し、解放された後それまでに満たされるので、pthread_cond_wait()でブロックを開始しwhile (avail == 0)ます。私は正しいですか?)

4

4 に答える 4

7

これpthread_cond_signal()は通常、待機中のスレッドを1つだけウェイクアップすることを目的としていることに注意してください(それが保証するすべてです)。しかし、それはもっと「偶然に」目覚める可能性があります。while (avail > 0)ループは2つの機能を実行します。

  • これにより、1つのスレッドがウェイクアップされ、キューに入れられたすべてのワークユニットを消費することが保証されます。
  • それは、最初のスレッドがそれらすべてを処理したので、行われるべき作業がないかもしれないときに、追加の「偶然に」目覚めたスレッドが行われるべき作業があると想定するのを防ぎます。

また、while (avail > 0)が完了した後、ワーカースレッドが再び条件を待機する前に、ワークユニットがキューに入れられた可能性がある競合状態を防ぎます。ただし、その競合は、をif呼び出す直前のテストによっても処理されpthread_cond_wait()ます。

基本的に、スレッドが目覚めたとき、それが知っているのは、それが消費するワークユニットがあるかもしれないが、そうではないかもしれないということだけです(別のスレッドがそれらを消費したかもしれません)

したがって、pthread_cond_signal()が呼び出されたときに発生するイベントのシーケンスは次のとおりです。

  • システムは、条件を待機している1つ以上のスレッドをウェイクアップします
  • ウェイクアップされたすべてのスレッドは、ミューテックスを取得しようとします。ミューテックスの目的であるため、特定の瞬間に取得できるのはそのうちの1つだけです。
  • 次に、そのスレッドが続行し、while (avail > 0)ループ内で作業を実行してから、ミューテックスを解放します
  • その時点で、以前にウェイクアップされた他のスレッドの1つがミューテックスを取得し、同じループを実行してから、ミューテックスを解放します。通常、使用可能なワークユニットはもうありません(最初のスレッドがすべてを消費したため)が、別のスレッドが追加のユニット(またはそれ以上)を追加した場合、このスレッドがその作業を処理します
  • 次のスレッドはミューテックスを取得し、同じロジックのセットを実行します
于 2011-06-29T15:14:35.843 に答える
2

pthread_cond_wait()信号が送信された/ウェイクアップされたら、指定されたミューテックスを取得する必要があります。別のスレッドがそのレースに勝った場合、ミューテックスが解放されるまで関数はブロックされます。したがって、アプリケーションの観点からは、現在のスレッドがミューテックスを保持するまで戻りません。待機は常にループ(while (avail == 0) { ...上記)で実行され、待機しているアプリケーション条件がまだ保持されていることを確認します(バッファーが空でない、利用可能な作業が増えるなど)。

お役に立てれば。

于 2011-06-29T13:45:55.563 に答える
1

コンテストに負けたスレッドは、ミューテックスのロックが解除されるとウェイクアップし、条件を再度チェックしてから、条件変数でスリープ状態になります。

于 2011-06-29T13:36:17.260 に答える
0

それらのいずれかがpthread_cond_wait()から戻ると、自動的にミューテックスを要求します。

ああ、でもそうではありません。「自動的に」ではありません。つまり、「自動的に」の意味によって異なります。pthread_cond_wait;の「アトミック」セマンティクスに混乱するかもしれません。ただし、そのセマンティクスはエントリ側で実行されます。スレッドは、ミューテックスを放棄する前に条件で待機するように登録されているため、スレッドにミューテックスがなく、まだ待機していないウィンドウはありません。変数に。

から戻る各スレッドpthread_cond_waitはミューテックスを取得する必要があるため、それを求めて競合します。ミューテックスの競争に負けた人は、と同じようにミューテックスをブロックする必要がありpthread_mutex_lockます。

出口でミューテックスを取得する方法はpthread_cond_wait、通常の操作としてモデル化できますpthread_mutex_lock。基本的に、スレッドは終了するためにミューテックスでキューに入れる必要があります。ミューテックスを取得した各スレッドは、関数から戻ります。他の人は、そのスレッドがミューテックスを放棄するまで待ってから、戻ることができます。

シグナルによってウェイクアップされたスレッドは、特別な適格性のために何らかの形で所有権が譲渡されるという意味で、ミューテックスを「自動的に」取得しません。まず、マルチプロセッサでは、ウェイクアップされたスレッドは、ミューテックスが利用可能な場合はミューテックスを奪う別のプロセッサですでに実行されているスレッドとの競争に負ける可能性があります。第2に、呼び出すスレッドpthread_cond_signal自体がミューテックスを放棄しておらず、無期限に保持し続ける可能性があります。つまり、ウェイクアップされたすべてのスレッドがミューテックスロック操作でキューに入れられ、pthread_mutex_lockそのスレッドがミューテックスを放棄するまで何も出現しません。 。

「自動」であるのはpthread_cond_wait、ミューテックスを再度取得するまで操作が戻らないため、アプリケーションがミューテックスを取得するための手順を実行する必要がないことだけです。

于 2016-07-29T13:35:10.653 に答える