std :: shared_ptr内部,弱计数超过预期

时间:2017-04-08 16:25:44

标签: c++ stl shared-ptr

在高级STL系列的一个episode(35:00)中,Stephan T Lavavej显示_Weaks,其值为0的计数器确定何时删除_Ref_count结构,等于活weak_ptr的数量,如果有活shared_ptrs,则加1。他解释说,由于线程安全,这是必要的:如果_Weaks仅等于weak_ptr的数量,那么当最后weak_ptr超出范围时,还需要检查{{1} },活动_Uses的计数器,用于检查是否可以删除shared_ptr。由于缺乏原子性,这是不可接受的。

假设_Ref_count =活着_Uses的数量,shared_ptr =活着_Weaks的数量,假设我们有以下情况:

  • weak_ptr = 0,_Uses = 1 ):上一个_Weaks超出范围,递减weak_ptr

  • _Weaks = 0,_Uses = 0 ):如果_Weaks等于0,则删除_Uses结构< / p>

在多线程应用程序中,什么可能出错,这迫使我们使用 _Ref_count =还活数_Weak +(weak_ptr的数量?1:0)< / em>实施?

1 个答案:

答案 0 :(得分:4)

想象一下以下场景。线程 A 拥有shared_ptr,线程 B 拥有相应的weak_ptr。因此,在您的实施中,我们有_Uses == 1_Weaks == 1

智能指针析构函数有两种可能的实现,两者都存在问题。

实施1:递减,然后检查

B weak_ptr已被销毁。减少_Weaks。我们有_Uses == 1_Weaks == 0 B 准备检查_Uses,但是......

上下文切换。

shared_ptr已被销毁。减少_Uses。我们有_Uses == 0_Weaks == 0。开始销毁_Ref_count

上下文切换。

B 现在开始检查_Uses。它是0.开始销毁_Ref_count

两个线程现在都在摧毁_Ref_count。不好。

实施2:检查,然后递减

B weak_ptr已被销毁。检查_Uses。它是1,不会发生破坏。 B 准备递减_Weaks,但......

Contex切换。

shared_ptr已被销毁。检查_Weaks。它是1,不会发生破坏。减少_Uses。我们有_Uses == 0_Weaks == 1。完成。

上下文切换。

B 现在可以减少_Weaks。我们有_Uses == 0_Weaks == 0。别无其他。

我们泄露了_Ref_count。不好。