在这个示例程序中,我试图避免使用前向声明和循环依赖来利用 lambda 函数(称为 data_race)
struct B{
int x;
std::thread* tid;
B(int _x){
x = _x;
tid = NULL;
}
~B(){
if(tid != NULL) delete tid;
}
void run(std::function<void(B*)> f){
auto body = [&f, this](){
f(this);
};
tid=new std::thread(body);
}
void wait(){
tid->join();
}
};
struct A{
int x;
std::mutex mtx;
A(int _x){
x = _x;
}
void foo(B* b){
std::unique_lock<std::mutex> lock(mtx);
x = b->x;
};
};
int main(){
A a(99);
std::vector<B> v;
auto data_race = [&a](B* b){ a.foo(b);};
for(int i=0; i<10; i++){
v.push_back(B(i));
}
for(int i=0; i<v.size(); i++){
v[i].run(data_race);
}
for(int i=0; i<v.size(); i++){
v[i].wait();
}
return 0;
}
但是 ThreadSanitizer 检测到来自 lambda 函数 data_race 的数据竞争。你能帮我理解为什么吗?A 内部的互斥体应该足以避免它。另外,你能帮我找到解决办法吗?
编辑:使用前向声明,不再检测到数据竞争,为什么?(仅发布结构,没有主要内容,对不起,很长的帖子)
struct B;
struct A{
int x;
std::mutex mtx;
A(int _x){
x = _x;
}
void foo(B* b);
};
struct B{
int x;
std::thread* tid;
B(int _x){
x = _x;
tid = NULL;
}
~B(){
if(tid != NULL) delete tid;
}
void run(A& a){
auto body = [&a, this](){
a.foo(this);
};
tid=new std::thread(body);
}
void wait(){
tid->join();
}
};
void A::foo(B* b){
std::lock_guard<std::mutex> lock(mtx);
x = b->x;
}