[解決済み] pthreadsの条件変数関数がmutexを必要とするのはなぜですか?
質問
を読んでいるところです。
pthread.h
条件変数に関連する関数(例えば
pthread_cond_wait(3)
) は、引数として mutex を必要とします。なぜ?私の知る限りでは、ミューテックスを作成するために
ちょうど
をその引数として使用するのですか?そのmutexは何をするものなのでしょうか?
どのように解決するのですか?
条件変数が実装されている(あるいは元々実装されていた)だけです。
ミューテックスは 条件変数そのもの . そのため、待ちを行う前にロックしておく必要があります。
待ち時間はミューテックスのロックを解除し、他の人が条件変数にアクセスできるようにします(シグナリングのため)。そして、条件変数がシグナルされるかブロードキャストされると、待機リストにある1つ以上のスレッドが起動され、そのスレッドのためにミューテックスが魔法のように再びロックされます。
条件変数がどのように機能するかを説明するために、一般的に次のような操作を目にすることがあります。次の例は、条件変数へのシグナルによって仕事を与えられるワーカスレッドです。
thread:
initialise.
lock mutex.
while thread not told to stop working:
wait on condvar using mutex.
if work is available to be done:
do the work.
unlock mutex.
clean up.
exit thread.
このループの中では、waitが戻ったときに利用できるものがあれば、作業が行われる。このスレッドが作業を停止するフラグを立てると(通常は他のスレッドが終了条件を設定し、このスレッドを起動するために条件変数をキックします)、ループが終了し、ミューテックスが解除されて、このスレッドは終了します。
上のコードはシングルコンシューマーモデルで、作業が行われている間、ミューテックスはロックされたままです。マルチコンシューマモデルでは、以下のようにします。 例 :
thread:
initialise.
lock mutex.
while thread not told to stop working:
wait on condvar using mutex.
if work is available to be done:
copy work to thread local storage.
unlock mutex.
do the work.
lock mutex.
unlock mutex.
clean up.
exit thread.
で、このコンシューマが作業している間、他のコンシューマが作業を受けることができるようにします。
コンディション変数を使うことで、ある条件をポーリングする負担から解放され、代わりに何かが起こったときに他のスレッドから通知されるようになります。別のスレッドは、次のようにそのスレッドに仕事が可能であることを伝えることができます。
lock mutex.
flag work as available.
signal condition variable.
unlock mutex.
よく間違ってスプリアスウェイクアップと呼ばれるものの大半は、一般に、複数のスレッドがその
pthread_cond_wait
を呼び出すと(ブロードキャスト)、1つはミューテックスを持って戻り、作業を行い、そして再び待機します。
そうすると、2つ目のシグナライズされたスレッドは、何もすることがないときに出てくることができます。そのため、作業が行われることを示す追加の変数を用意する必要がありました(ここではcondvarとmutexのペアで本質的にmutex保護されていました - ただし、他のスレッドはそれを変更する前にmutexをロックする必要がありました)。
それは でした。 技術的には、スレッドが他のプロセスからキックされることなく条件待ちから戻ることは可能ですが(これは正真正銘の偽装ウェイクアップです)、私の長年の pthreads に関する作業、コードの開発/サービス、およびユーザーとしての作業のすべてにおいて、私は一度もこれを受けたことはありません。多分それは、HPがまともな実装をしていたからでしょう :-)
いずれにせよ、誤ったケースを処理する同じコードは、作業可能フラグが設定されないので、本物の偽のウェイクアップも処理します。
関連
-
[解決済み] munmap_chunk(): 無効なポインタ
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] longをフォーマットするprintfの引数は何ですか?
-
[解決済み] C言語標準に準拠した構造体の初期化方法
-
[解決済み] C言語のi++と++iに性能差はあるのでしょうか?
-
[解決済み] C 言語の配列へのポインタ/ポインタの配列の曖昧さ解消
-
[解決済み] フリーは、どのように無料化を知っているのですか?
-
[解決済み] FortranはC言語よりも重い計算を最適化しやすいですか?
-
[解決済み】C言語の「static」関数とは?
-
[解決済み] pthread_cond_wait で spurious wakeup が発生するのはなぜですか?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
libc++abi.dylib: NSException タイプの捕捉されない例外で終了するエラー
-
[C] Error [Error] 代入の左オペランドとして lvalue が必要です。
-
[解決済み] Code::Blocks アプリケーションをコンパイルできない
-
[解決済み] C言語でchar配列をコピーする方法は?
-
[解決済み] flexible array member not at end of structエラーの原因は何ですか?
-
[解決済み] C関数から文字列を返す
-
[解決済み] C言語で関数型プログラミングを行うためのツールにはどのようなものがありますか?
-
[解決済み] C言語では「?」演算子は何をするのですか?
-
[解決済み] C言語における「static」の意味とは?
-
[解決済み] .aファイル、.soファイルとは何ですか?