是否可以使用信号量作为工作线程的全局暂停?

时间:2013-07-28 23:46:35

标签: multithreading threadpool

我正在考虑使用信号量作为工作线程池的暂停机制,如下所示:

// 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(不退出)循环退出。因此,要将它与传统的worker-wait-for-condition相关联以获得工作:我的工作人员等待所需的文件副本,而你看到的while循环正在执行所请求的工作。您可以将上面的do_work视为do_piece_of_work。

1 个答案:

答案 0 :(得分:1)

信号量方法的问题是工作线程必须不断检查工作。他们占用了所有可用的CPU资源。最好使用互斥锁和条件(信令)变量(如第二个示例中所示),这样线程只有在有事可做时才会被唤醒。

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

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

这是一个简单的示例,其中所有工作线程都被唤醒,即使只有一个工作人员实际上可以成功地从队列中获取工作。如果你想要更高的效率,使用一个条件变量数组,每个工作线程一个,然后只是发出“下一个”的信号,使用“next”算法,你可以根据需要简单或复杂。