我正在考虑使用信号量作为工作线程池的暂停机制,如下所示:
// 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。
答案 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”算法,你可以根据需要简单或复杂。