我读过
“多个线程可以同时读取和写入不同的 shared_ptr 对象,即使这些对象是共享所有权的副本。” ( MSDN:标准 C++ 库中的线程安全)
这是否意味着更改 shared_ptr 对象是安全的?
例如,下一个代码是否被认为是安全的:
shared_ptr<myClass> global = make_shared<myClass>();
...
//In thread 1
shared_ptr<myClass> private = global;
...
//In thread 2
global = make_shared<myClass>();
...
在这种情况下,我可以确定线程 1 private
将具有原始值 global
或线程 2 分配的新值,但无论哪种方式,它都会有一个有效的 shared_ptr 到 myClass?
==编辑==
只是为了解释我的动机。我想要一个共享指针来保存我的配置,并且我有一个线程池来处理请求。
所以 global
是全局配置。
thread 1
在开始处理请求时采用当前配置。
thread 2
正在更新配置。 (仅适用于未来的请求)
如果它有效,我可以以这种方式更新配置,而不会在请求处理过程中破坏它。
原文由 Roee Gavirel 发布,翻译遵循 CC BY-SA 4.0 许可协议
你所读的并不意味着你认为它意味着什么。首先,尝试 shared_ptr 本身的 msdn 页面。
向下滚动到“备注”部分,您将了解问题的实质。基本上,一个
shared_ptr<>
指向一个“控制块”,它是如何跟踪有多少shared_ptr<>
对象实际上指向“真实”对象。所以当你这样做时:虽然这里只有 1 次调用通过
make_shared
分配内存,但有两个“逻辑”块您不应该同样对待。一个是int
存储实际值,另一个是控制块,它存储了所有shared_ptr<>
使其工作的“魔法”。只有控制块本身是线程安全的。
为了强调,我把它放在了自己的位置上。
shared_ptr
的 内容 不是线程安全的,也不是写入同一个shared_ptr
实例。这里有一些东西可以证明我的意思:这很好,实际上您可以在所有线程中随心所欲地执行此操作。然后当
local_instance
被破坏(超出范围)时,它也是线程安全的。有人可以访问global_instance
这不会有什么不同。您从 msdn 中提取的代码段基本上意味着“对控制块的访问是线程安全的”,因此可以根据需要在不同的线程上创建和销毁其他shared_ptr<>
实例。这可以。它 会 影响
global_instance
对象,但只是间接的。它指向的控制块将被递减,但以线程安全的方式完成。local_instance
将不再指向与global_instance
相同的对象(或控制块)。如果
global_instance
从任何其他线程(你说你正在做的)访问,这几乎肯定是不好的。如果您这样做,它需要一个锁,因为您正在写入global_instance
生活的任何地方,而不仅仅是从中读取。所以从多个线程写入一个对象是不好的,除非你已经通过锁保护它。因此,您可以通过分配新的shared_ptr<>
对象来读取global_instance
对象,但您不能写入它。a
的值未定义。它可能是 7,也可能是 3,或者也可能是其他任何东西。shared_ptr<>
实例的线程安全仅适用于管理相互初始化的shared_ptr<>
实例,而不是它们指向的实例。为了强调我的意思,看看这个:
shared_ptr<>
是确保多个对象 所有者 确保对象被破坏的机制,而不是确保多个 线程 可以正确访问对象的机制。您仍然需要一个单独的同步机制才能在多个线程中安全地使用它(例如 std::mutex )。考虑它的最佳方式 IMO 是
shared_ptr<>
确保指向同一内存的多个副本 本身 没有同步问题,但对指向的对象没有任何作用。就这样对待。