C++ std::shared_ptr 线程安全解释

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9127816/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 12:20:26  来源:igfitidea点击:

std::shared_ptr thread safety explained

c++c++11shared-ptr

提问by Goofy

I'm reading http://gcc.gnu.org/onlinedocs/libstdc++/manual/shared_ptr.htmland some thread safety issues are still not clear for me:

我正在阅读http://gcc.gnu.org/onlinedocs/libstdc++/manual/shared_ptr.html并且一些线程安全问题对我来说仍然不清楚:

  1. Standard guarantees that reference counting is handled thread safe and it's platform independent, right?
  2. Similar issue - standard guarantees that only one thread (holding last reference) will call delete on shared object, right?
  3. shared_ptr does not guarantee any thread safety for object stored in it?
  1. 标准保证引用计数是线程安全的并且它是独立于平台的,对吗?
  2. 类似的问题 - 标准保证只有一个线程(持有最后一个引用)会在共享对象上调用 delete ,对吗?
  3. shared_ptr 不保证存储在其中的对象的任何线程安全?

EDIT:

编辑:

Pseudo code:

伪代码:

// Thread I
shared_ptr<A> a (new A (1));

// Thread II
shared_ptr<A> b (a);

// Thread III
shared_ptr<A> c (a);

// Thread IV
shared_ptr<A> d (a);

d.reset (new A (10));

Calling reset() in thread IV will delete previous instance of A class created in first thread and replace it with new instance? Moreover after calling reset() in IV thread other threads will see only newly created object?

在线程 IV 中调用 reset() 将删除在第一个线程中创建的 A 类的先前实例并将其替换为新实例?此外,在 IV 线程中调用 reset() 后,其他线程只会看到新创建的对象?

采纳答案by Nicu Stiurca

As others have pointed out, you've got it figured out correctly regarding your original 3 questions.

正如其他人指出的那样,您已经正确地解决了最初的 3 个问题。

But the ending part of your edit

但是你编辑的结尾部分

Calling reset() in thread IV will delete previous instance of A class created in first thread and replace it with new instance? Moreover after calling reset() in IV thread other threads will see only newly created object?

在线程 IV 中调用 reset() 将删除在第一个线程中创建的 A 类的先前实例并将其替换为新实例?此外,在 IV 线程中调用 reset() 后,其他线程只会看到新创建的对象?

is incorrect. Only dwill point to the new A(10), and a, b, and cwill continue to point to the original A(1). This can be seen clearly in the following short example.

是不正确的。只有d将指向新A(10),和ab以及c将继续指向原始A(1)。在以下简短示例中可以清楚地看到这一点。

#include <memory>
#include <iostream>
using namespace std;

struct A
{
  int a;
  A(int a) : a(a) {}
};

int main(int argc, char **argv)
{
  shared_ptr<A> a(new A(1));
  shared_ptr<A> b(a), c(a), d(a);

  cout << "a: " << a->a << "\tb: " << b->a
     << "\tc: " << c->a << "\td: " << d->a << endl;

  d.reset(new A(10));

  cout << "a: " << a->a << "\tb: " << b->a
     << "\tc: " << c->a << "\td: " << d->a << endl;

  return 0;                                                                                                          
}

(Clearly, I didn't bother with any threading: that doesn't factor into the shared_ptr::reset()behavior.)

(显然,我没有打扰任何线程:这不会影响shared_ptr::reset()行为。)

The output of this code is

这段代码的输出是

a: 1 b: 1 c: 1 d: 1

a: 1 b: 1 c: 1 d: 10

a: 1 b: 1 c: 1 d: 1

a: 1 b: 1 c: 1 d: 10

回答by NothingMore

  1. Correct, shared_ptrs use atomic increments/decrements of a reference count value.

  2. The standard guarantees only one thread will call the delete operator on a shared object. I am not sure if it specifically specifies the last thread that deletes its copy of the shared pointer will be the one that calls delete (likely in practice this would be the case).

  3. No they do not, the object stored in it can be simultaneously edited by multiple threads.

  1. 正确,shared_ptrs 使用引用计数值的原子递增/递减。

  2. 该标准保证只有一个线程会调用共享对象上的删除操作符。我不确定它是否明确指定了删除其共享指针副本的最后一个线程将是调用 delete 的线程(实际上可能是这种情况)。

  3. 不,他们没有,存储在其中的对象可以由多个线程同时编辑。

EDIT: Slight followup, if you want to get an idea of how shared pointers work in general you might want to look at the boost::shared_ptrsource: http://www.boost.org/doc/libs/1_37_0/boost/shared_ptr.hpp.

编辑:稍微跟进,如果您想了解共享指针的工作原理,您可能需要查看boost::shared_ptr源代码:http: //www.boost.org/doc/libs/1_37_0/boost/shared_ptr.hpp

回答by Lothar

std::shared_ptris not thread safe.

std::shared_ptr不是线程安全的。

A shared pointer is a pair of two pointers, one to the object and one to a control block (holding the ref counter, links to weak pointers ...).

共享指针是一对两个指针,一个指向对象,一个指向控制块(保存引用计数器,指向弱指针的链接......)。

There can be multiple std::shared_ptr and whenever they access the control block to change the reference counter it's thread-safe but the std::shared_ptritself is NOT thread-safe or atomic.

可以有多个 std::shared_ptr 并且每当它们访问控制块以更改引用计数器时,它都是线程安全的,但它std::shared_ptr本身不是线程安全的或原子的。

If you assign a new object to a std::shared_ptrwhile another thread uses it, it might end up with the new object pointer but still using a pointer to the control block of the old object => CRASH.

如果您将一个新对象分配给std::shared_ptr另一个线程使用它的同时,它可能会以新对象指针结束,但仍然使用指向旧对象的控制块的指针 => CRASH。