在尝试围绕this question中显示的问题时,我发现自己陷入了[util.smartptr.shared] / 4中的以下句子:
[...]
use_count()
中的更改不反映可能引入数据争用的修改。
我不明白我应该如何阅读,以及我应该得出什么结论。 以下是一些解释:
use_count()
不会引入数据争用(但这应该仅由该函数的const
保证 - 以及相应的库范围保证)use_count()
返回的值不受(“不反映”?)影响需要原子性或同步的操作的结果(但这些相关操作是什么?)use_count()
以原子方式执行,但不会阻止CPU或编译器重新排序(即没有顺序一致性,但为什么不提及特定模型?)对我而言,以上似乎都没有从这句话中得出结论,而我却无法解释它。
答案 0 :(得分:11)
当前的措辞来自库issue 896,它还解决了shared_ptr
是否应该是线程安全的问题,因为可以访问拥有相同对象的不同shared_ptr
(特别是,同时复制和破坏来自不同的线程。该讨论的结论是shared_ptr
应该是线程安全的;保证这一点的机制是假装shared_ptr
成员函数只访问shared_ptr
对象本身而不是它的堆上控制块:
为了确定是否存在数据争用,成员函数只访问和修改
shared_ptr
和weak_ptr
个对象本身,而不是它们所引用的对象。
这里“他们引用的对象”是指控制块。
然而,这提出了一个问题;如果我们假装拥有相同对象的不同shared_ptr
不访问控制块,那么肯定use_count()
不能改变?通过使use_count()
成为一个凭空产生结果的神奇函数来补丁:
use_count()
中的更改不反映可能引入数据争用的修改。
也就是说,use_count()
可以从一个调用更改为下一个调用,但这并不意味着发生了数据竞争(或潜在的数据竞争)。这可能比该句子的先前措辞更清楚:
[注意:这是事实,尽管这些功能经常修改use_count() - 结束记录]
答案 1 :(得分:2)
这意味着use_count()
中的代码无锁或使用互斥锁来锁定关键部分。换句话说,你可以从线程中调用它而不必担心竞争条件。
答案 2 :(得分:2)
我认为当我们添加上一句话时,意图会变得更加清晰:
为了确定是否存在数据争用,成员函数应仅访问和修改shared_ptr和weak_ptr对象本身,而不是它们引用的对象。 use_count()中的更改不反映可能引入数据争用的修改。
所以,最后一句话只是强调与第一句话相同的观点。例如,如果我复制shared_ptr
,其使用次数将会增加,以反映shared_ptr
已被复制的事实 - 因此use_count()
的结果将会更改 - 但这是不允许访问(并且,特别是,不允许修改)指针对象,因此它永远不会在使用该指针对象时引入数据争用。