首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ThreadSanitizer报告的数据竞争

ThreadSanitizer报告的数据竞争
EN

Stack Overflow用户
提问于 2019-09-17 23:29:04
回答 1查看 1.2K关注 0票数 3

我使用Clang-8并启用线程清除器来编译下面的代码。

代码语言:javascript
复制
std::atomic<std::string*> ptr {nullptr};
int data {0};

void producer() {
  std::string* p  = new std::string("Hello");
  data = 42; 
  ptr.store(p, std::memory_order_release);
}

void consumer() {
  std::string* p2; 
  if(!(p2 = ptr.load(std::memory_order_relaxed))) {
     // Data is not ready, just return
     return ;
  }
  std::atomic_thread_fence(std::memory_order_seq_cst);
  assert(data == 42); // Never fired
}

int main() {
  std::thread t1(producer);
  std::thread t2(consumer);
  t1.join();   t2.join();
}

线程清除器报告全局变量data上的数据竞争警告。为什么这被认为是一场数据竞赛?

代码语言:javascript
复制
==================
WARNING: ThreadSanitizer: data race (pid=20388)
  Read of size 4 at 0x000001191718 by thread T2:
    #0 consumer() <null> (a.out+0x4afe32)
    #1 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) <null> (a.out+0x4b1fad)
    #2 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) <null> (a.out+0x4b1ee0)
    #3 decltype(std::__invoke(_S_declval<0ul>())) std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) <null> (a.out+0x4b1e88)
    #4 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() <null> (a.out+0x4b1e28)
    #5 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() <null> (a.out+0x4b1c1c)
    #6 <null> <null> (libstdc++.so.6+0xbd66e)

  Previous write of size 4 at 0x000001191718 by thread T1:
    #0 producer() <null> (a.out+0x4afcca)
    #1 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) <null> (a.out+0x4b1fad)
    #2 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) <null> (a.out+0x4b1ee0)
    #3 decltype(std::__invoke(_S_declval<0ul>())) std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) <null> (a.out+0x4b1e88)
    #4 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() <null> (a.out+0x4b1e28)
    #5 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() <null> (a.out+0x4b1c1c)
    #6 <null> <null> (libstdc++.so.6+0xbd66e)

  Location is global 'data' of size 4 at 0x000001191718 (a.out+0x000001191718)

  Thread T2 (tid=20391, running) created by main thread at:
    #0 pthread_create <null> (a.out+0x424775)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xbd924)
    #2 main <null> (a.out+0x4afec1)

  Thread T1 (tid=20390, finished) created by main thread at:
    #0 pthread_create <null> (a.out+0x424775)
    #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0xbd924)
    #2 main <null> (a.out+0x4afeae)

SUMMARY: ThreadSanitizer: data race in consumer()
==================
ThreadSanitizer: reported 1 warnings

更新

我已经阅读了Why does ThreadSanitizer report a race with this lock-free example?并使用Clang-8编译了代码。它不显示任何数据竞争警告。所以我觉得我的案子不一样。

EN

回答 1

Stack Overflow用户

发布于 2019-11-12 23:42:08

您的示例在将42存储到数据和写入数据值之间没有同步。编译器可以自由地在producer中重新排序这两个数据,这意味着即使在设置障碍和进行检查之后,数据的值也是未定义的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57983170

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档