gpt4 book ai didi

c++ - ThreadSanitizer 检测到数据竞争,问题出在哪里?

转载 作者:太空宇宙 更新时间:2023-11-04 15:29:44 25 4
gpt4 key购买 nike

在这个示例程序中,我试图避免使用前向声明和利用 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;
}

最佳答案

您正在传递对函数局部的引用 f到 lambda body ,由 thread 调用构造函数。

当线程函数到达body 内部的调用时,该对象可能不再存在.

扩展一下:

run 创建的新线程将执行 body 的拷贝, 这是一个包含对对象 [&f] 的引用 ( f ) 的 lambda , 具有函数范围 run当主线程离开时将被销毁 run .

线程函数会调用operator()关于其引用 ff(this) 行中在 body .如果 run 发生,此调用已经导致未定义的行为在线程函数执行此调用之前,主线程到达范围结束。这里的数据竞争是,主线程可能会写入 f 的访问内存。销毁它,与对 f 的内存的读取访问不同步在生成的线程中。

完全可以避免中间函数对象:

template<typename F>
void run(const F& f){
auto body = [this](){
f(this);
};

tid=new std::thread(body);
}

这将采用外层 lambda data_race作为引用,将此引用复制到 body而且,只要你确定 data_racemain超过所有线程,避免了前面提到的数据竞争。

您编辑的代码做了类似的事情,即它消除了 run 的本地对象. abody将引用 Amain 中定义其中,只要main保证其生命周期超出线程的生命周期,此时不会引起任何问题。

关于c++ - ThreadSanitizer 检测到数据竞争,问题出在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57741185/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com