2009-07-16 9 views
44

私はpthreadと条件を学習しています。私の知る限り、一般的な待機中のスレッドを言うことができるように、このようなものです:私はスレッドをウェイクアップするpthread_cond_signal()を使用している場合でも、ラインwhile(!condition)が必要な理由Pスレッドと待機条件

pthread_mutex_lock(&m); 
while(!condition) 
    pthread_cond_wait(&cond, &m); 
// Thread stuff here 
pthread_mutex_unlock(&m); 

私は理解できない何かがあります。

私はpthread_cond_broadcast()を使用している場合、私はすべて待機中のスレッドを覚ますと、そのうちの一つは、ミューテックスをアンロック(したがって、起床別に実行を転送する前に、再び条件が偽作ることができるので、私は、条件をテストする必要があることを理解することができますその時点で実行すべきではないスレッド)。 しかし、私がpthread_cond_signal()を使用した場合、私はちょうどスレッドを起きるので、条件が真でなければなりません。したがってコードは次のようになります。

pthread_mutex_lock(&m); 
pthread_cond_wait(&cond, &m); 
// Thread stuff here 
pthread_mutex_unlock(&m); 

私は起こりうる偽信号について何かを読んでいます。理由はこれだけですか?なぜ私は偽のシングルを持っているのですか?それとも私には得られない何か他のものがありますか?

私は信号のコードは次のようであると仮定します。

pthread_mutex_lock(&m); 
condition = true; 
pthread_cond_signal(&cond); // Should wake up *one* thread 
pthread_mutex_unlock(&m); 

答えて

43

pthread_cond_waitをwhileループに置く本当の理由は、偽のウェークアップのためではありません。条件変数に偽のウェークアップがない場合でも、一般的なタイプのエラーを検出するにはループが必要です。どうして?複数のスレッドが同じ条件で待っていれば何が起こるか考えてみましょう:

Thread 1       Thread 2   Thread 3 
check condition (fails) 
(in cond_wait) unlock mutex 
(in cond_wait) wait 
           lock mutex 
           set condition 
           signal condvar 
           unlock mutex 
                lock mutex 
                check condition (succeeds) 
                do stuff 
                unset condition 
                unlock mutex 
(in cond_wait) wake up 
(in cond_wait) lock mutex 
<thread is awake, but condition 
is unset> 

ここでの問題は、スレッドが潜在的にそのスレッドが待っていたものは何でも「盗む」に別のスレッドを許可する、待機する前にミューテックスを解放しなければならないということです。 1つのスレッドだけがその状態で待機できることが保証されていない限り、スレッドが起動するときにその条件が有効であると仮定するのは間違いです。

+1

。投票された。これは受け入れられた答えより多くの注目を集めるべきです。 –

15

は、あなたが条件をチェックしないと仮定します。実行して

もちろん
Sender        Receiver 
locks mutex 
sets condition 
signals condvar, but nothing 
    is waiting so has no effect 
releases mutex 
            locks mutex 
            waits. Forever. 

はあなたの2番目のコード例は、これを避けることができます::次に通常あなたが起こって、次の悪いことを避けることができない(少なくとも、あなたは1行のコードでそれを避けることができない)

pthread_mutex_lock(&m); 
if (!condition) pthread_cond_wait(&cond, &m); 
// Thread stuff here 
pthread_mutex_unlock(&m); 

それでは受信者が1人しかなく、cond_signalが目を覚ます唯一のものだった場合は、条件が設定されたときに目が覚めるでしょうループは必要ありません。 2番目の「if」が真実でない理由をカバーしていません。

+0

論理理由(無限の待ち)のために "if"が必要ですが、実際には実装の問題(スプリアス信号)のためにしばらく時間が必要です。 – Emiliano

+0

私は最初にpthreadsライブラリを使用したとき、私は同じ質問をしました。私は状態変数のチェックを省き、待機が発生する前に私のプログラムがシグナルを出します。これは待機/信号機能の全ポイントです。ミューテックスによって保護された状態の変化を待って信号を送る。 –

関連する問題