0

次のように、ワーカースレッドのプールの一時停止メカニズムとしてセマフォを使用することを考えています。

// main thread
for N jobs:
    semaphore.release()
    create and start worker

// worker thread
while (not done)
    semaphore.acquire()
    do_work
    semaphore.release()

ここで、すべてのワーカーを一時停止したい場合は、セマフォで使用可能なカウント全体を取得できます。私はそれがより良いと思っています:

if (paused)
    paused_mutex.lock
    wait for condition (paused_mutex)
do_work

または、より良い解決策はありますか?

セマフォでそれを行うことの1つの欠点は、すべてのワーカーが解放されるまでメインスレッドがブロックされることだと思います. 私の場合、反復ごとの作業単位は非常に小さいため、おそらく問題にはなりません。

更新: 明確にするために、私のワーカーはファイル コピーのように機能するデータベース バックアップです。ファイルが正常にコピーされると、while(not quit) ループが終了します。これを従来の worker-waits-for-condition に関連付けて作業を取得します。私のワーカーは必要なファイルのコピーを待機し、while ループは要求された作業を実行しています。上記の do_work は do_piece_of_work と考えることができます。

4

1 に答える 1

1

セマフォ アプローチの問題は、ワーカー スレッドが常に作業をチェックしなければならないことです。利用可能なすべての CPU リソースを使い果たしています。ミューテックスと条件 (シグナリング) 変数 (2 番目の例のように) を使用して、スレッドが何かを行う必要がある場合にのみスレッドが起動されるようにすることをお勧めします。

また、mutex を保持する時間はできるだけ短くすることをお勧めします。これを行う従来の方法は、WORK QUEUE を作成し、mutex を使用してキューの挿入と削除を同期することです。メイン スレッドがワーク キューに挿入され、ワー​​カーが起動されます。ワーカーはミューテックスを取得し、キューからアイテムを削除してから、ミューテックスを解放します。ワーカーがアクションを実行します。これにより、ワーカー スレッドとメイン スレッド間の同時実行性が最大化されます。以下に例を示します。

// main thread
create signal variable
create mutex

for N jobs:
    create and start worker

while (wait for work)
    // we have something to do
    create work item
    mutex.acquire();
    insert_work_into_queue(item);
    mutex.release();

    //tell the workers
    signal_condition_variable()

//worker thread
while (wait for condition)
    mutex.acquire();
    work=remove_item_from_queue();
    mutex.release();

    if (work) do(work);

これは、キューから作業を取り出すことに実際に成功するのは 1 つのワーカーだけであるにもかかわらず、すべてのワーカー スレッドが起動される単純な例です。さらに効率が必要な場合は、条件変数の配列をワーカー スレッドごとに 1 つ使用してから、必要に応じて単純または複雑な「次」のアルゴリズムを使用して、「次の」変数にシグナルを送るだけです。

于 2013-07-29T00:17:53.777 に答える