12

これは一般的な質問です。たとえば、現在 2 つの子スレッドが を呼び出しpthread_cond_wait(&cond1,&mutex)ており、両方とも待機しています。次に、親スレッドが呼び出します

pthread_cond_signal(&cond1);
pthread_cond_signal(&cond1);

次に、私の質問は、待機中の 2 つのスレッドの両方が起動されることが保証されているかどうかです (起動された最初のスレッドが実行の特定の段階で後でミューテックスを解放し、2 番目のスレッドがそれを取得できるとします)。

この質問をする理由は、Unix システム レベルのシグナルの場合、シグナル (たとえばSIGCHLD) がキューに入れられないため、同じタイプの複数のシグナルが連続して配信されると失われる可能性があるためです。pthread_cond_signalスケジューラがたまたま親スレッドに2回続けてシグナルを送らせた場合に失われないように、実装が異なるのだろうか?

4

3 に答える 3

13

簡単な答え:

pthread_cond_signal()条件変数でブロックされているスレッドの少なくとも 1 つをウェイクアップしますが、それ以上は保証されません (参考までに、pthread_cond_broadcast()すべてのブロックされたスレッドをウェイクアップするために使用します)。

ここから:

pthread_cond_signal() 呼び出しは、指定された条件変数 cond でブロックされているスレッドの少なくとも 1 つのブロックを解除します (cond でブロックされているスレッドがある場合)。

pthread_cond_broadcast() 呼び出しは、指定された条件変数 cond で現在ブロックされているすべてのスレッドのブロックを解除します。

より長い答え:

したがって、仕様によると、ブロック解除は同期的に行われると想定します。つまり、 への最初の呼び出しによってブロックが解除されたスレッドは、pthread_cond_signal()への 2 番目の呼び出しによってブロックが解除されたと見なされるpthread_cond_signal()ため、他のスレッドがウェイクされます。上。

ただし、これが特定の pthread 実装に当てはまるかどうかはわかりません (現在、glibc の Web サイトは非常に危険なため、コードにアクセスして参照することはできません)。

おそらくまだ実装されていないが、仕様に含まれているという回答:

pthread_cond_signal()ただし、指定された条件変数でどのスレッドが実際にブロックされるかを決定する方法に関して、仕様が最近少し書き直されたことに注意する必要がありますが、pthread_cond_broadcast()すべての実装がまだ追いついているわけではないと思います。

この件に関する長い議論はここにあります。新しい仕様は次のとおりです。

pthread_cond_broadcast() および pthread_cond_signal() 関数は、指定された条件変数 cond でブロックされているスレッドがある場合、アトミックに決定します。この決定は、pthread_cond_broadcast() または pthread_cond_signal() 呼び出し中の未指定の時間に行われます。pthread_cond_broadcast() 関数は、これらのスレッドをすべてブロック解除します。pthread_cond_signal() 関数は、これらのスレッドの少なくとも 1 つのブロックを解除します。

したがって、結論: 仕様の専門家の解釈者でなくても、新しいテキストは、これが同期的に発生するという仮定をサポートしていると言えます。つまり、pthread_cond_signal()2 つのブロックされたスレッドが使用可能な状態で を 2 回連続して呼び出すと、両方のスレッドが起動します。

私はこれについて 100% 確信しているわけではないので、詳しく説明できる人がいれば、遠慮なくそうしてください。

于 2013-03-18T20:35:36.293 に答える
0

これが古いスレッドであることは知っていますが(しゃれは意図していません)、典型的な実装は次のように機能します。

条件変数には、現在スリープ状態にあり、シグナルが送られるのを待っているスレッドのキューが含まれます。

ロックには、ロックを取得しようとしたが別のスレッドによって保持されていたため、スリープ状態になったスレッドのキューがあります。

cond_wait は、実行中のスレッドを条件変数のキューに追加し、ロックを解除して、それ自体をスリープ状態にします。

cond_signal は、1 つのスリープ状態のスレッドを条件変数のキューからロックのキューに移動するだけです。

実行中のスレッドがロックを解放すると、スリープ状態のスレッドがロックのキューから削除され、ロックの所有権がそのスリープ状態のスレッドに移され、そのスリープ状態のスレッドが起動されます。

cond_signal が複数のスレッドを起動する可能性があると仕様に記載されている理由を聞かないでください...

于 2017-06-25T23:01:25.807 に答える