对于多线程,shared_ptr销毁是否安全?
Is shared_ptr destruction safe with multiple threads?
我有两个类似的类:
class Foo {
public:
void bar() {
std::lock_guard<std::mutex> lock(m_mutex);
m_data.push_back('x');
}
private:
std::string m_data;
std::mutex m_mutex;
};
class Pool {
public:
static std::shared_ptr<Foo> Create(int index) {
std::lock_guard<std::mutex> lock(m_mutex);
if (m_pool.size() > 10) {
m_pool.erase(m_pool.begin());
}
std::shared_ptr<Foo>& ptr = m_pool[index];
if (!ptr) ptr.reset(new Foo);
return ptr;
}
private:
static std::mutex m_mutex;
static std::map<int, std::shared_ptr<Foo>> m_pool;
};
和几个运行此代码的线程:
void parallel_function(int index) {
// several threads can get the same index
std::shared_ptr<Foo> foo = Pool::Create(index);
foo->bar();
}
Cppreference说
所有成员函数(包括复制构造函数和拷贝赋值)都可以在shared_ptr的不同实例上由多个线程调用,而无需额外的同步,即使这些实例是相同对象的副本并共享所有权。如果多个执行线程不同步地访问同一个shared_ptr,并且其中任何一个访问使用了shared_ptr的非const成员函数,则会发生数据争用;原子函数的shared_ptr重载可用于防止数据争用。
两个问题:
由于
Pool::Create
总是返回shared_ptr
的副本,我假设每个shared_ptr
的复制和销毁是线程安全的,如果它发生在m_pool.erase
或parallel_function
的末尾。这是正确的吗?我调用
shared_ptr::operator->
,这是一个const成员函数,函数Foo::bar
是线程安全的。这里是否存在数据竞赛?
总结一下我的评论。
- 是的,这是线程安全的,因为你在不同的线程中操作单独的
shared_ptr
副本。这是传递shared_ptr
s副本的少数情况之一。 -
operator->
是const成员。所以基本上你的代码是好的,只要Foo::bar是无种族的站真(它现在显然是)。
相关文章:
- 通过网络、跨平台传递std::变体是否安全
- 在类型和包装器之间reinterpret_cast是否安全<Type>?
- 跨 DLL 边界访问虚拟方法是否安全/可能?
- 静态 constexpr 类成员变量对多线程读取是否安全?
- 在函数结束后使用指向变量的指针是否安全?
- 逐字节删除 void* 是否安全?
- 在 RAII 构造中修改 RVO 值是否安全?
- 线程调用的函数对对象删除是否安全?
- 将对象的字节复制到数组并再次复制回来是否安全
- 使用枚举为数组编制索引是否安全?
- 返回从字符串文本创建的静态string_view是否安全?
- 在cstlib中将#include_next替换为#include是否安全
- 由并发无序映射查找线程调用的函数是否安全?
- 使用 c++ 原子时编写"y=++x"是否安全?
- 从另一个线程发出信号是否安全?
- 从其存储的回调中删除 std::函数是否安全
- 使用 std::vector::swap 方法在C++中交换两个不同的向量是否安全?
- 当我在C++中调用 struce 的只读静态成员时,线程是否安全
- 同时调用 ASIO 对象的 API 是否安全?
- 使用自己的迭代器分配容器是否安全?