c++多线程 shared_ptr 生命期问题

2023-06-06 19:41:07 +08:00
 kkkbbb

在书上看到这个例子:

划线处使用 swap 方式,而不是 data_=newData,解释是:使旧数据的析构发生在临界区外,缩小临界区的范围,但是我理解通过这种方式,newData 虽然指向了旧数据的引用,但是出了 if 判断作用域引用不也为 0 ,也会产生析构啊,不知道是哪理解错了?

883 次点击
所在节点    程序员
8 条回复
codehz
2023-06-06 19:48:40 +08:00
所以这个函数在 C++20 就直接移除了
kkkbbb
2023-06-06 19:52:00 +08:00
@codehz 所以这种方式旧数据的析构也是发生在临界区里吧
codehz
2023-06-06 19:56:45 +08:00
被移除的是 unique(),因为多线程环境下不能确保不会出现 toctou 的问题(
----
整个判定 unique 的方法就不对,如果到处都有 lock 保护,那判不判断 unique 都一样
唯一想到的用例就是懒拷贝,此时 mutex 可能不是同一个,那还是有 toctou 的问题,可能在判定 unique 的时候它还是 unique 的,但是到了更新的时候就不 unique 了
kkkbbb
2023-06-06 20:06:05 +08:00
@codehz 就算真的不是 unique ,“使旧数据的析构发生在临界区外,缩小临界区的范围”这句话的意思是什么?
codehz
2023-06-06 20:17:24 +08:00
@kkkbbb 你是说在 if !unique 里面不用 data_=newData ?那说明文章在脱裤子放屁
operator=的实现基本上等价于
shared_ptr<T>(r).swap(*this);
return *this;
它这里手动复制 Map ,除非 MapPtr 里有做什么 non trivial 的事情,否则基本上可以认为没有区别
kkkbbb
2023-06-06 21:17:51 +08:00
@codehz 还是有区别的吧,operator= newData 的指向的对象不会发生变化,swap 会交换指向的内容
codehz
2023-06-06 21:27:11 +08:00
@kkkbbb 但也就复制一份右侧的而已,而右侧的无论如何也不会在这个位置和别人共享访问,所以没有区别(除了多复制一次)
要避免额外复制的话,用 std::move()让它移动过去就可以了)
kkkbbb
2023-06-08 08:46:25 +08:00
乌龙了,图片上的代码和书上还有点区别,书上的 lock 临界区是在 if 作用域里,所以解释的没问题。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/946396

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX