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();
}
All member functions (including copy constructor and copy assignment) can be called by multiple threads on different instances of shared_ptr without additional synchronization even if these instances are copies and share ownership of the same object. 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.
两个问题:
因为 Pool::Create
总是 returns 个 shared_ptr
的副本,我假设每个 shared_ptr
的副本和销毁都是线程安全的,如果它发生在 m_pool.erase
或 parallel_function
结束时。这是正确的吗?
我调用了shared_ptr::operator->
,它是一个const成员函数,Foo::bar
这个函数是线程安全的。这里有数据竞赛吗?
总结一下我的意见。
- 是的,这是线程安全的,因为您在不同的线程中操作
shared_ptr
的单独副本。这是传递 shared_ptr
s 的副本实际上是合理的少数情况之一。
operator->
是一个 const member。所以基本上你的代码是好的,只要 Foo::bar 是无竞争的(现在显然是这样)。
我有两个类类似这样的:
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();
}
All member functions (including copy constructor and copy assignment) can be called by multiple threads on different instances of shared_ptr without additional synchronization even if these instances are copies and share ownership of the same object. 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.
两个问题:
因为
Pool::Create
总是 returns 个shared_ptr
的副本,我假设每个shared_ptr
的副本和销毁都是线程安全的,如果它发生在m_pool.erase
或parallel_function
结束时。这是正确的吗?我调用了
shared_ptr::operator->
,它是一个const成员函数,Foo::bar
这个函数是线程安全的。这里有数据竞赛吗?
总结一下我的意见。
- 是的,这是线程安全的,因为您在不同的线程中操作
shared_ptr
的单独副本。这是传递shared_ptr
s 的副本实际上是合理的少数情况之一。 operator->
是一个 const member。所以基本上你的代码是好的,只要 Foo::bar 是无竞争的(现在显然是这样)。