我将bfs :: directory_iterator队列更改为std :: string队列,并且令人惊讶地解决了这个问题。
嗨,我有一种直觉,认为我做错了。
我已经实现(或尝试过)线程池模式。
N个线程从队列中读取,但我遇到了一些麻烦。这就是我得到的:
//inside a while loop
bool isEmpty;
bfs::directory_iterator elem;
{
boost::mutex::scoped_lock lock(this->queue_mutex);
isEmpty = this->input_queue.isEmpty();
if (!isEmpty){
elem= *(this->input_queue.pop());
}
else{
continue;
}
}
scoped_lock是否仍在if的主体内部工作?我开始相信它不会(经过许多测试后)。如果没有,是否有任何范围的方法来做到这一点(即不是明确的锁定解锁方式)
提前致谢。
向队列添加元素的代码如下所示
//launches the above code, passing a reference to mutex and queue.
Threads threads(queue,queue_mutex);
for (bfs::directory_iterator dir_it:every file in directory){
boost::mutex::scoped_lock lock(queue_mutex);
queue.push(dir_it);
}
我放置一个cout来控制poped文件名,如果我按下2个文件(file1)和(file2),并使用2个线程,我得到两个“file2”。
class Threads{
boost::thread::thread_group group;
Thread (N){
//also asigns a reference to a queue and a mutex.
for(i 1..N){
//loop is posted above.
group.add(new boost::thread(boost::bind(&loop,this)));
}
}
};
答案 0 :(得分:1)
发布的代码看起来很好 - 如果你看到问题可能还有一些其他地方应该采取锁定而不是(例如为队列添加内容的代码)。
答案 1 :(得分:0)
不,如果它在if
内移动,锁将无法工作,因为在检查空虚时会出现竞争条件。检查和锁定之间可能已删除最后一个元素。
答案 2 :(得分:0)
我会将锁添加到队列中...管理队列外部的锁是很棘手的,往往会混淆代码,但是由于暴露了未锁定的数据结构,因此非常脆弱。
似乎是为队列提供实用工具的模式是try_pop& try_push方法。 .NET的Parallel Extensions在System.Collections.Concurrent.ConcurrentQueue中使用了这种模式。
使用无锁队列或通过简单地嵌入队列并使用适当的接口锁定容器来完成此操作。 Anthony Williams在如何使用std :: queue here进行了很好的发布。
您的代码可能如下所示:
//inside a while loop
bfs::directory_iterator elem;
while (this->input_queue.pop(*elem))
{
... // do something
}