条件変数では、排他的にチェックして更新する必要がある関連する「条件」(この場合はデータ行) があると想定されます (したがってミューテックス)。他のどのメカニズムを選択する場合でも、「作業キュー」への排他的アクセスを確保する方法を理解する必要があります (それが単一のスロットであるか実際のキューであるかに関係なく)。
共有キューを使用すると、データ構造に対して常に 2 つのライター (メイン スレッド + 目的のワーカー) と N-1 のリーダーが存在します。整合性を確保するために、読み書きロック (rwlock) を使用できます。
または、N 個の個別のキュー (ワーカーごとに 1 つ) を持つこともできます。データ行のコピーを各ワーカーにプッシュします。
一度に複数のスレッドを起動する限り、ワーカーを「スリープ」させ (たとえば、select() を使用)、pthread_signal() を使用して (ループで) 起動させることができます。
pthread_barrier_wait()を使用することもできます。
pthread_barrier_wait() 関数は、バリアによって参照されるバリアで参加スレッドを同期します。呼び出しスレッドは、必要な数のスレッドがバリアを指定して pthread_barrier_wait() を呼び出すまでブロックします。
必要な数のスレッドがバリアを指定して pthread_barrier_wait() を呼び出した場合、定数 PTHREAD_BARRIER_SERIAL_THREAD が 1 つの未指定のスレッドに返され、残りの各スレッドにゼロが返されます。この時点で、バリアは、それを参照した最新の pthread_barrier_init() 関数の結果としての状態にリセットされます。
- pthread_barrier_init()でバリアを初期化します(カウント = 1 + ワーカー数)
- 各ワーカーで、ループ内で pthread_barrier_wait() を呼び出します。それが戻ると、新しいデータの準備ができています
- メインスレッドで、 pthread_barrier_wait() を呼び出してワーカーに通知します
残念ながら (OP に記載されているように)、次の反復では、以前にアクティブ化されたワーカーがジョブを完了するまで、ワーカーは起動されません。
より単純なアーキテクチャでは、メイン スレッドがイベントを適切なワーカーにディスパッチします (すべてのワーカーを起動して、どのワーカーが意図した受信者であるかを判断させるのではなく)。ワーカーと同じ数のコアがない限り、テストは実際には並行して行われません。また、ワーカーを並行して実行するのに十分なコアがある場合でも、そのうちの N-1 は、テストが完了する前に「勝者」がジョブを引き受けたことを学習しないため、すべてのコアの合計作業量は高くなります。 .