web-dev-qa-db-ja.com

条件変数-pthread_cond_wait()を呼び出す前にpthread_cond_signal()を呼び出すことが論理エラーであるのはなぜですか?

POSIXスレッドのチュートリアルで書かれています https://computing.llnl.gov/tutorials/pthreads/ 論理エラーです。

私の質問は、なぜそれが論理エラーなのかということです。

私のプログラムでは、これらのシグナルを使用する必要がありますが、_cond_wait状態になるスレッドがあることを保証できません。テストしようとしましたが、何も起こりません。これは予期しない動作または悪化を引き起こす可能性がありますか?

ありがとうございました!

25
Asher Saban

ブレイズの答えが最も近くなりますが、完全には明確ではありません。
条件変数は、条件の変化を通知するためにのみ使用する必要があります

スレッド1は条件をチェックします。条件が満たされない場合、彼は条件が満たされるまで条件変数を待ちます。条件が最初にチェックされるため、条件変数が通知されたかどうかを気にする必要はありません。

pthread_mutex_lock(&mutex); 
while (!condition)
    pthread_cond_wait(&cond, &mutex); 
pthread_mutex_unlock(&mutex);

スレッド2は条件を変更し、条件変数を介して変更を通知します。彼はスレッドが待機しているかどうかを気にしません:

pthread_mutex_lock(&mutex); 
changeCondition(); 
pthread_mutex_unlock(&mutex); 
pthread_cond_signal(&cond)

結論は次のとおりです。通信は何らかの条件で行われます。条件変数は待機中のスレッドのみをウェイクアップするため、条件をチェックできます

条件の例:

  • キューは空ではないため、キューからエントリを取得できます
  • ブールフラグが設定されているため、スレッドは、他のスレッドが続行しても問題ないことを通知するまでs待機します。
  • ビットセットの一部のビットが設定されているため、待機中のスレッドは対応するイベントを処理できます

参照 pthreadの例

37
stefaanv

私の2セント:* pthread_cond_wait()*の呼び出しがブロックされていないスレッドが* pthread_cond_signal()*を呼び出すことの副作用がわかりません。これは実際には実装の詳細です。スレッド/ timimgモデルが待機とシグナルの間の厳密な順序を保証しない場合は、おそらく別の同期メカニズムを検討する必要があります[単純なセマフォ、たとえば]スレッドAが同期点に到達していない場合でも、スレッドBからセマフォに信号を送ることができる場合。スレッドAが同期ポイントに到達すると、セマフォがインクリメントされていることがわかり、クリティカルセッションに入ります。

5
sergico

条件変数を使用すると、あるスレッドが別のスレッドを待機からウェイクアップできます。これらは、条件をトリガーした瞬間に待機しているスレッドがある場合にのみ機能します。これを確実に行う方法は、待機中のスレッドが条件にリンクされているミューテックスをロックし、シグナリングスレッドが条件をトリガーする前にそのミューテックスをロックすることです。つまり、シグナリングスレッドは、他のスレッドがミューテックスをロックしていて、現在待機している場合にのみ、ミューテックスをロックして条件をトリガーできます。

私はブーストに最も精通しているので、この例ではそれを使用します。

// A shared mutex, global in this case.
boost::mutex myMutex;

// Condition variable
boost::condition_variable myCondition;

void threadProc()
{
    // Lock the mutex while the thread is running.
    boost::mutex::scoped_lock guard( myMutex );

    while( true )
    {
        // Do stuff, then...

        myCondition.wait( guard ); // Unlocks the mutex and waits for a notification.
    }
}

void func()
{
    // Function wants to trigger the other thread. Locks the mutex...
    boost::mutex::scoped_lock guard( myMutex );

    // Since the mutex is locked, we know that the other thread is
    // waiting on the condition variable...
    myCondition.notify_all();
}

対応する待機がないときに条件変数を通知することは、信号を受信するものがないため、論理エラーです。条件変数は、シグナル状態のままではありません。

3
RobH

この信号が失われることを気にしない場合、エラーはありません。後で来る待機中のスレッドがcond_wait()からすぐにウェイクアップすることを期待している場合にのみエラーになります。

これはpthread_condの通常の使用例であるため、チュートリアルではこの論理エラーを呼び出します。ただし、クラッシュすることはなく、予期しない動作は発生しません。通常の実行フローでは、cond_wait()にスレッドがない場合でも、cond_signal()が発行される場合があります。つまり、ライターがキューに別のデータを追加すると、すべてのリーダーがメッセージ処理を実行している可能性があります。

3
blaze

人を落ち着かせるものが見当たらないので、答えを書きます。また、そのチュートリアルで「論理エラー」についての奇妙な不穏な警告に出くわしました。 _pthread_cond_signal_に関するPOSIXドキュメントの記事 には、この「エラー」については何もないことに注意してください。これは、この用語の不幸な選択であるか、チュートリアルの作成者の一部の明白な間違いであると確信しています。彼らの主張は、この状況でプロセスがエラーで終了するか、この状況を許可するプログラムが正しくないかのように解釈される可能性があります。そのようなことは何も真実ではありません。このような状況は一般的です。ドキュメントには、

condで現在ブロックされているスレッドがない場合、pthread_cond_signal()およびpthread_cond_broadcast()関数は効果がありません。

だから心配しないで幸せになりなさい。

1
beroal