多线程 std::shared_ptr 读/写

multithread std::shared_ptr read / write

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

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

使用:

globalTable[idx].reset(newBucket);

另一个线程有时会使用 :

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

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

并非 std::shared_ptr 上的所有操作都是 thread-safe。

具体来说,reference-counts 是原子管理的,但 有责任确保你访问的 std::shared_ptr 实例没有被同时修改。

您未能履行该责任,导致 data-race 和预期的未定义行为,在您的案例中表现为 double-free。

重置并不能保证线程安全。

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

To satisfy thread safety requirements, the reference counters are typically incremented using an equivalent of std::atomic::fetch_add with std::memory_order_relaxed (decrementing requires stronger ordering to safely destroy the control block).

如果多个线程访问同一个 shared_ptr 你可能会出现竞争条件。

If multiple threads of execution access the same shared_ptr without synchronization and any of those accesses uses a non-const member function of shared_ptr then a data race will occur; the shared_ptr overloads of atomic functions can be used to prevent the data race.

您的函数 reset 不是 const,因此属于该类别。您需要使用互斥锁或其他同步机制。

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