我正在设计一个系统,其中一个工作池从一个队列中弹出作业,我希望主线程等待所有这些完成。这是我到目前为止所提出的(伪代码):
// Main
launch_signal();
for (auto &worker : pool) {
// create unique_lock
if (!worker.done)
worker.condition_variable.wait(lock, worker.done);
}
// Worker
if (queue.empty()) {
mutex.lock();
this->done = true;
mutex.unlock();
this->condition_variable.notify_one();
// wait for launch signal from Main
} else {
mutex.lock();
auto job = queue.pop();
mutex.unlock();
job.execute();
}
因此Main
表示作业可用,然后等待每个工作人员发出信号。 Worker
同时不断从队列中弹出作业直到空,然后信号完成并进入等待发射信号。
我的问题:什么是更有效的算法呢?
答案 0 :(得分:1)
现有代码似乎无需持有互斥锁即可访问queue.empty()
。除非queue
对象本身是线程安全的,(或者至少queue.empty()
方法被明确记录为线程安全的),否则这将是未定义的行为。
所以第一个改进是修复这个可能的错误。
否则,这是一个相当库存,经过实战考验的工作池实现。这里没有太大的改进空间。
我可以做的唯一建议是,如果工作线程的数量是N
,并且在锁定互斥锁之后线程发现队列中有J
个作业,则线程可以删除{ {1}}作业(除法结果至少为1)一次从队列中进行,然后按顺序执行,假设所有其他线程都会这样做,并且作业大小相同平均来说,要做的时间。这将最大限度地减少锁争用。