我试图在一段时间内找到答案,但我失败了。
让我们假设我们从一个线程创建了shared_ptr
。然后我们将此shared_ptr
传递给另外2个线程(例如,使用某个队列)。所以从这一刻起,原始shared_ptr
有两个副本,指向同一个原始指针。
两个所有者线程都将从队列中获取此shared_ptr
的副本。然后他们会将它传递给另一个线程或将其销毁。
问题是 - 它安全吗?原始指针是否会被正确销毁(没有竞争引用计数器?)
答案 0 :(得分:9)
C ++标准几乎不保证线程安全。 std::shared_ptr
的引用计数是唯一的例外:它保证表现为原子访问的变量。我相信这在§20.7.2.2/ 4中的短语中已经编纂成了:
use_count()
中的更改不反映可能引入数据争用的修改。
boost::shared_ptr
offers the same guarantees:
shared_ptr对象提供与内置类型相同的线程安全级别。 shared_ptr实例可以由多个线程同时“读取”...。不同的shared_ptr实例可以被多个线程同时“写入”...(即使这些实例是副本,并在下面共享相同的引用计数。)
答案 1 :(得分:5)
不同的shared_ptr实例可以被多个线程同时“写入”(使用诸如operator =或reset之类的可变操作访问)(即使这些实例是副本,并且在下面共享相同的引用计数。)
(强调我的)
所以关键在于你是否复制线程之间的boost::shared_ptr
。如果您创建副本(使用shared_ptr
的“安全”方式),您不必担心线程安全。但是,如果您通过引用或指针传递shared_ptr
,因此在不同的线程中使用实际相同的shared_ptr
,则必须担心线程安全性,如文档中所述。
答案 2 :(得分:0)
我想在多线程用例中的boost共享指针中发布我的注释用于引用计数。评论是回答“升压共享指针引用计数中是否存在任何竞争条件?”的问题。
对于大多数主流编译器,至少在提升1.35之后,我的简单回答是“否”。 boost / detail / shared_count.hpp中定义的boost实现名为“add_ref_copy”。该函数将调用为各个编译器定义的相应原子函数。例如,Windows版本将调用“BOOST_INTERLOCKED_INCREMENT”以原子方式递增计数(详细信息请参见\ sp_counted_base_w32.hpp)。 X86的Linux gcc将调用atomic_increment(...)(详见详细信息\ sp_counted_base_gcc_x86.hpp)。每个单独的编译器都实现了线程安全机制,以确保以有效的方式更新引用计数。有些代码甚至是用汇编语言编写的。
现在我的简单答案中有一个警告。您确实需要确保您的编译器包含在boost的祝福列表中,以进行多线程安全引用计数。如果您不确定是否可以定义“BOOST_SP_USE_PTHREADS”来驱动boost以使用pthread库以原子方式进行引用计数更新(通过为pthread解决方案包含boost / detail / sp_counted_base_pt.hpp)。