我有一个关于Boost::Thread
和Mutex
的新手问题。
我想启动以下Worker
的许多并行实例,并且所有这些实例都写入相同的std::vector
:
struct Worker {
std::vector<double>* vec;
Worker(std::vector<double>* v) : vec(v) {}
void operator() {
// do some long computation and then add results to *vec, e.g.
for(std::size_t i = 0; i < vec->size(); ++i) {
(*vec)[i] += some_value;
}
}
};
我理解工作者必须在写入之前锁定vec
并在完成时将其解锁(因为所有工作者都写入相同的向量)。但是我该怎么表达呢?
答案 0 :(得分:8)
你需要一个boost :: mutex来保护向量,你可以使用一个boost :: mutex :: scoped_lock来锁定构造函数中的互斥锁,并在析构函数中解锁它
请记住,您需要使用相同的互斥锁无处不在,您可以在其中访问vec
的实例,无论是读取还是写入。
为了让你前进,你可以做类似的事情:
struct Worker {
boost::mutex &vec_mutex;
Worker(std::vector<double>* v,boost::mutex &v_mutex) : vec(v),vec_mutex(v_mutex) {}
void operator() {
// do some long computation and then add results to *vec, e.g.
boost::mutex::scoped_lock lock(vec_mutex);
for(std::size_t i = 0; i < vec->size(); ++i) {
(*vec)[i] += some_value;
}
}
};
对于更高级的东西,你应该进一步封装vector和mutex,或者迟早你会忘记这些需要连接,你可以在某个地方访问vec
而不需要锁定导致非常困难调试问题。对于像这个例子这样的问题,我宁愿让工人使用他们自己的单独的向量,并在工人完成时将结果组合在一个控制线程中。
答案 1 :(得分:0)
OT但有用的信息我希望 - 因为你正在更新这个向量(或者只是为了最佳实践),考虑iterators迭代向量元素。通过不需要使用vector<double>::operator[]
来提高工作者代码将减少工作线程的总等待时间。
for(std::vector<double>::iterator iter = vec->begin(); iter != vec->end(); ++iter) {
*iter += some_value;
}