C++ C++;共享ptr和threadsanitazer报告数据竞争

C++ C++;共享ptr和threadsanitazer报告数据竞争,c++,multithreading,boost-asio,shared-ptr,thread-sanitizer,C++,Multithreading,Boost Asio,Shared Ptr,Thread Sanitizer,这是来自threadsanitazer(clang)的粘贴,它报告数据竞争 谷歌搜索似乎这是threadsanitazer的一个问题(例如) 让我们假设它看起来像(刚才是手工编写的,所以它不是工作代码): 并从主线程定期添加或删除元素 void add_elem(int id) { auto my = std::make_shared<my>(thread_service, id); my->start(); mymap[id] = my; } void del

这是来自threadsanitazer(clang)的粘贴,它报告数据竞争

谷歌搜索似乎这是threadsanitazer的一个问题(例如)

让我们假设它看起来像(刚才是手工编写的,所以它不是工作代码):

并从主线程定期添加或删除元素

void add_elem(int id)
{
  auto my = std::make_shared<my>(thread_service, id);
  my->start();
  mymap[id] = my;
}

void del_elem(int id)
{ 
  auto my = mymaps.at(id);
  mymap.erase(id); //erase first shared_ptr instace from map

  // run this in the same thread as start_and_do_async is running so no data race can happen (io_service is thread safe in this case)
  thread_service.post[my]()
  {
    my.stop(); //this will finally destroy myclass and free memory when shared_ptr is out of scope
  });
}
void添加元素(int-id)
{
auto my=std::使线程共享(线程服务,id);
我的->开始();
mymap[id]=我的;
}
无效删除元素(内部id)
{ 
auto my=mymaps.at(id);
mymap.erase(id);//从地图中删除第一个共享的安装
//在与start_和do_async运行的线程相同的线程中运行它,这样就不会发生数据争用(在这种情况下,io_服务是线程安全的)
线程_service.post[my]()
{
my.stop();//当shared_ptr超出范围时,这将最终破坏myclass并释放内存
});
}
因此,在这种情况下,根据文档判断(其中声明distinct shared_ptr(boost或std)允许从多个线程进行读/写访问),是否存在数据竞争

这段代码是否正确地为一个指针创建了两个不同的共享\u ptr instance

在shared_ptr.h中,我可以看到原子操作,所以我只想确认是thread sanitazer报告误报的问题


在我的测试中,这可以正常工作,没有内存泄漏(正确删除共享的ptr实例并调用析构函数)、segfaults或任何其他(10小时插入/删除元素-每秒100个或每秒1个)

假设
共享的ptr
线程安全文档与其实现匹配,然后,
共享_ptr
上的数据竞争报告为假阳性。线程在共享同一实例所有权的
shared_ptr
的不同实例上运行。因此,不存在对同一
共享\u ptr
实例的并发访问


话虽如此,我还是想强调一下,在这个示例中,
myclass::usocket\u
的线程安全性只依赖于一个处理
io\u服务的线程,它以隐式方式有效地执行。如果多个线程服务于
io_服务
,则可以使用显式线程来提供线程安全性。有关Boost、Asio和代码< >代码>的一些线程安全性的详细信息,请考虑阅读答案。

是的,对于您所写的所有这些原因,只有一个线程处理IoOService。我确实理解示例中的原理,但在这里,我实际上不完全确定是否使用del_elem函数正确创建和删除了两个共享的安装。在接受你的回答之前,你能确认一下吗?(使用boost::make_shared和boost::shared_ptr会引发异常:bad_weak_ptr,这让我想知道,即使我没有正确尝试调试可能出现的问题)@juzerKicker,尽管映射返回
shared_ptr&
auto
会将
my
类型推断为
shared\u ptr
而不是引用,因此会制作一份副本。此外,lambda通过值捕获创建另一个
共享的\u ptr
副本,其生存期几乎在调用完成处理程序后立即结束。如果在
make_shared
期间抛出
bad_-weak_ptr
,则可能会从构造函数内部调用
shared_from_this()
,这违反了至少一个
shared_ptr
实例拥有该对象的前提条件。确定。感谢您的解释(我已经看到了报告中的问题,当从_调用共享_时,构造函数和对象不存在,但我的情况不是这样。但是我还没有正确地测试过这种情况。我可能已经在某个地方混合了boost和std关于共享_ptr的内容,但效果并不好)
new boost::thread([&]()
{   
     boost::asio::io_service::work work(thread_service);
     thread_service.run();
}); 
void add_elem(int id)
{
  auto my = std::make_shared<my>(thread_service, id);
  my->start();
  mymap[id] = my;
}

void del_elem(int id)
{ 
  auto my = mymaps.at(id);
  mymap.erase(id); //erase first shared_ptr instace from map

  // run this in the same thread as start_and_do_async is running so no data race can happen (io_service is thread safe in this case)
  thread_service.post[my]()
  {
    my.stop(); //this will finally destroy myclass and free memory when shared_ptr is out of scope
  });
}