在高级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>实施?
答案 0 :(得分:4)
想象一下以下场景。线程 A 拥有shared_ptr
,线程 B 拥有相应的weak_ptr
。因此,在您的实施中,我们有_Uses == 1
和_Weaks == 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
。不好。
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
。不好。