多线程std :: shared_ptr读/写

时间:2018-02-24 22:56:52

标签: c++ smart-pointers

我有一个使用std :: shared_ptr的双重免费bug并试图了解原因。我在多线程环境中使用shared_ptr,一个线程有时会替换全局数组中的某个元素

std::shared_ptr<Bucket>  globalTable[100]; // global elements storage

使用:

globalTable[idx].reset(newBucket);

,另一个线程有时使用:

读取此表
std::shared_ptr<Bucket> bkt(globalTable[pIdx]);
// do calculations with bkt-> items

在此之后我收到双重自由错误,而AddressSanitizer说第二个代码试图释放被第一个被破坏的对象。怎么可能?据我所知,shared_ptr必须是完全线程安全的。

2 个答案:

答案 0 :(得分:2)

并非std::shared_ptr上的所有操作都是线程安全的。

具体来说,引用计数是以原子方式管理的,但 负责确保您访问的std::shared_ptr实例不会同时修改。

您没有履行该责任,导致数据争用和预期的未定义行为,在您的案例中显示为双重免费。

答案 1 :(得分:2)

重置并不能保证您保持线索状态。

分配和引用计数是线程安全的,如此处所述

  

为了满足线程安全要求,参考计数器是   通常使用等效的std :: atomic :: fetch_add递增   与std :: memory_order_relaxed(递减需要更强   命令安全销毁控制块。)

如果多个线程访问同一个shared_ptr,您可能会遇到竞争条件。

  

如果多个执行线程没有访问相同的shared_ptr   同步和任何这些访问使用非const成员   shared_ptr的功能然后会发生数据竞争; shared_ptr   原子函数的重载可用于防止数据竞争。

您的功能重置是非常数,因此属于该类别。您需要使用互斥锁或其他同步机制。

http://en.cppreference.com/w/cpp/memory/shared_ptr