タスクのキューを持つスレッドを実装しています。最初のタスクがキューに追加されるとすぐに、スレッドが実行を開始します。
スレッドをウェイクアップするために pthread 条件変数を使用する必要がありますか、それともより適切なメカニズムがありますか?
pthread_cond_signal()
他のスレッドがブロックされているのpthread_cond_wait()
ではなく、何かを実行しているときに呼び出すと、どうなりますか? 信号が失われますか?
タスクのキューを持つスレッドを実装しています。最初のタスクがキューに追加されるとすぐに、スレッドが実行を開始します。
スレッドをウェイクアップするために pthread 条件変数を使用する必要がありますか、それともより適切なメカニズムがありますか?
pthread_cond_signal()
他のスレッドがブロックされているのpthread_cond_wait()
ではなく、何かを実行しているときに呼び出すと、どうなりますか? 信号が失われますか?
pthread_cond_broadcast() および pthread_cond_signal() 関数は、cond で現在ブロックされているスレッドがない場合は効果がありません。
Semaphoresを使用することをお勧めします。基本的に、タスクがキューに挿入されるたびに、セマフォを「アップ」します。ワーカー スレッドは、セマフォを "ダウン" することによってブロックします。タスクごとに 1 回「アップ」されるため、ワーカー スレッドは、キューにタスクがある限り続行されます。キューが空の場合、セマフォは 0 になり、ワーカー スレッドは新しいタスクが到着するまでブロックされます。セマフォは、ワーカーがビジー状態で複数のタスクが到着した場合にも簡単に処理できます。挿入/削除をアトミックに保つために、キューへのアクセスをロックする必要があることに注意してください。
セマフォは、キューがすでにスレッドセーフである場合にのみ有効です。また、セマフォの実装によっては、トップ カウンタ値によって制限される場合があります。最大値を超える可能性はほとんどありません。
これを行う最も簡単で正しい方法は次のとおりです。
pthread_mutex_t queue_lock;
pthread_cond_t not_empty;
queue_t queue;
push()
{
pthread_mutex_lock(&queue_lock);
queue.insert(new_job);
pthread_cond_signal(¬_empty)
pthread_mutex_unlock(&queue_lock);
}
pop()
{
pthread_mutex_lock(&queue_lock);
if(queue.empty())
pthread_cond_wait(&queue_lock,¬_empty);
job=quque.pop();
pthread_mutex_unlock(&queue_lock);
}
信号は失われますが、その場合は信号が失われるようにします。ウェイクアップするスレッドがない場合、信号は目的を果たしません。(誰も何かを待っていない場合、それが起こったときに誰にも通知する必要はありませんよね?)
条件変数を使用すると、信号が失われると、スレッドが「火の中に眠る」ことはありません。すでに火災が発生しているときにスリープ状態になるようにスレッドを実際にコーディングしない限り、「シグナルを保存する」必要はありません。火事が始まると、ブロードキャストはスリープ状態のスレッドをウェイクアップします。そして、すでに火事が発生しているときにスリープ状態になるスレッドをコーディングするには、かなり巧妙である必要があります。
すでに示唆されているように、セマフォが最良の選択であるべきです。固定サイズのキューが必要な場合は、(従来のプロデューサー/コンシューマーのように) 2 つのセマフォを使用するだけです。
artyom コードでは、pop() 関数の "if" を "while" に置き換えて、スプリアスなウェイクアップを処理することをお勧めします。