50

私はpthreadと待機条件を学んでいます。私が知る限り、典型的な待機スレッドは次のようになります。

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

私が理解できないのは、スレッドをウェイクアップするためwhile(!condition)に使用しても、なぜラインが必要なのかということです。pthread_cond_signal()

pthread_cond_broadcast()使用する場合、条件をテストする必要があることを理解できます。これは、待機中のすべてのスレッドをウェイクアップし、そのうちの1つが、ミューテックスのロックを解除する前に条件を再度falseにする可能性があるためです(したがって、その時点で実行されるべきではない別のウェイクアップされたスレッドに実行を転送します点)。しかし、私が使用する場合、私は1つの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);
4

2 に答える 2

47

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つだけであることが保証されていない限り、スレッドがウェイクアップしたときに条件が有効であると想定するのは誤りです。

于 2011-01-27T20:47:37.603 に答える
17

状態をチェックしないと仮定します。その場合、通常、次の悪いことが起こるのを避けることはできません(少なくとも、1行のコードでそれを避けることはできません)。

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

もちろん、2番目のコード例では、次のようにしてこれを回避できます。

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

その場合、受信機が最大で1つしかなくcond_signal、それをウェイクアップできる唯一のものである場合、条件が設定されたときにのみウェイクアップするため、ループは必要ありません。nosは、2番目の「if」が正しくない理由をカバーしています。

于 2009-07-16T10:27:30.273 に答える