[解決済み] pthread_cond_wait() と pthread_cond_signal() を理解する。
質問
一般的に言えば
pthread_cond_wait()
と
pthread_cond_signal()
は以下のように呼び出されます。
//thread 1:
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
do_something()
pthread_mutex_unlock(&mutex);
//thread 2:
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
ステップの内容は
-
pthread_cond_wait(&cond, &mutex);
が呼ばれると、ミューテックスのロックが解除されます。 -
スレッド 2 はミューテックスをロックし、次のように呼び出します。
pthread_cond_signal()
であり、ミューテックスのロックを解除する。 -
スレッド1では
pthread_cond_wait()
が呼び出され、再びミューテックスをロックします。
さて、スレッド 2 では、次のように
pthread_cond_signal()
が呼び出されます。
pthread_mutex_unlock(&mutex)
が実行されると、スレッド1によってロックされているミューテックスのロックを解除したいように思えます。私の理解に何か間違いがあるのでしょうか?
また
pthread_cond_wait()
は、同じcond-mutexの組に対して1つのスレッドからしか呼び出されません。しかし、"The pthread_cond_signal() function shall unblock at least one of the threads that are blocked on the specified condition variable cond (if any threads are blocked on cond)." とあることから、この場合は
pthread_cond_wait()
は、同じcond-mutexの組に対して多くのスレッドから呼び出される可能性があるのですか?
どのように解決するのですか?
pthread_cond_signal
は、ミューテックスのロックを解除しない(ミューテックスへの参照を持たないので解除できない。では、何を解除すればいいのかどうやって知ることができるのか?)。 シグナルを送るスレッドはミューテックスを保持する必要はありませんが、条件変数に基づくほとんどのアルゴリズムでは保持することになります。
pthread_cond_wait
はスリープする直前にミューテックスのロックを解除しますが(ご指摘の通り)、その後、スリープから復帰する前に、シグナルを受けたときにミューテックスを再要求します(これは待つ必要があるかもしれません)。 ですから、もしシグナルを送るスレッドがミューテックスを保持している場合(通常の場合)、シグナルを送るスレッドがミューテックスのロックを解除するまで、待機中のスレッドは処理を進めません。
条件バーの一般的な使い方は、次のようなものです。
thread 1:
pthread_mutex_lock(&mutex);
while (!condition)
pthread_cond_wait(&cond, &mutex);
/* do something that requires holding the mutex and condition is true */
pthread_mutex_unlock(&mutex);
thread2:
pthread_mutex_lock(&mutex);
/* do something that might make condition true */
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
2つのスレッドは、ミューテックスがアクセスを保護しているいくつかの共有データ構造を持っています。 最初のスレッドは、ある条件が真になるまで待ち、それからすぐに何らかの処理を行いたいとします(条件チェックと処理の間に他のスレッドが入り込んで条件を偽にするようなレースコンディションの機会はありません)。 2 番目のスレッドは、その条件が真になるような処理をしているので、それを待っている可能性のある人を起こす必要があります。
関連
-
[解決済み】文字列関数で'char const*'のインスタンスを投げた後に呼び出されるterminate [閉店].
-
[解決済み】「Expected '(' for function-style cast or type construction」エラーの意味とは?
-
[解決済み】「std::operator」で「operator<<」にマッチするものがない。
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み】なぜ、サイズ8の初期化されていない値を使用するのでしょうか?
-
[解決済み】変数やフィールドがvoid宣言されている
-
[解決済み】'std::cout'への未定義の参照
-
[解決済み] 1ビットのセット、クリア、トグルはどのように行うのですか?
-
[解決済み] static_cast, dynamic_cast, const_cast, reinterpret_cast はいつ使うべきですか?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Visual Studio 2015で「非標準の構文; '&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】C++ - 解放されるポインタが割り当てられていないエラー
-
[解決済み】致命的なエラー LNK1169: ゲームプログラミングで1つ以上の多重定義されたシンボルが発見された
-
[解決済み】'cout'は型名ではない
-
[解決済み】C++の変数はイニシャライザーを持っているが、不完全な型?
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み】C++プログラムでのコンソールの一時停止
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み] 数値定数の前にunqualified-idを付けて、数値を定義することを期待する。
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較