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

还是有更好的解决方案?

我想用信号量做的一个缺点是主线程将阻塞,直到所有工作人员都释放。就我而言,每次迭代的工作单元非常小,因此可能不会成为问题。

更新:澄清一下,我的工作人员是充当文件副本的数据库备份。当文件被成功复制时,while(not quit) 循环退出。因此,将其与传统的 worker-waits-for-condition 联系起来以获取工作:我的 worker 等待所需的文件副本,而您看到的 while 循环正在执行请求的工作。你可以把我上面的 do_work 想象成 do_piece_of_work。

4

1 回答 1

1

信号量方法的问题是工作线程必须不断检查工作。它们正在消耗所有可用的 CPU 资源。最好使用互斥锁和条件(信号)变量(如第二个示例中所示),以便线程仅在它们有事可做时才被唤醒。

保持互斥锁的时间越短越好。执行此操作的传统方法是创建一个 WORK QUEUE 并使用互斥锁来同步队列插入和删除。主线程插入工作队列并唤醒worker。工作人员获取互斥锁,从队列中删除一个项目,然后释放互斥锁。现在工人执行动作。这最大限度地提高了工作线程和主线程之间的并发性。这是一个例子:

// 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);

这是一个简单的示例,其中所有工作线程都被唤醒,即使只有一个工作线程实际上会成功地将工作从队列中取出。如果您想要更高的效率,请使用一组条件变量,每个工作线程一个,然后只发出“下一个”的信号,使用“下一个”的算法,该算法与您想要的一样简单或复杂。

于 2013-07-29T00:17:53.777 回答