从C++20 shared_ptr移除unique()方法浅析多线程同步
@[TOC](从C++20 shared_ptr移除unique()方法浅析多线程同步)
std::shared_ptr的unique()方法做了什么事情?
unique()作为std::shared_ptr的成员函数,它检查当前shared_ptr持有的对象,是不是该对象的唯一持有者。也就是说检查shard_ptr的引用计数是否为1。大概的实现如下
bool unique() {return this->use_count() == 1; }工程上我曾用它来管控对象的所有权。如:多个对象同时通过std::shared_ptr持有a_object,但是我希望b_object是最后一个持有a_object的对象,也就是说希望a_object在b_object释放,于是,在b_object中设计如下函数:
class a_object; class b_object { void check_unique() {if (a_holder_.unique()) {a_holder_.reset();} else {// 一段时间之后再执行check_unique()...} } shared_ptr<a_object> a_holder_; };shared_ptr()引用计数通过什么保证线程安全?
根据gcc 10.02源码,shared_ptr引用计数的类型是_Atomic_word原子变量,增加引用计数使用memory_order_acq_rel的cas,而返回引用计数的函数use_count()使用memory_order_relaxed atomic load。下面分别分析:
通过以上的分析,我们知道了:
为什么C++20移除了unique()方法?
std::shared_ptr的unique()方法在C++17中被废弃,在C++20中被移除。在cpp reference中有如下说明:
This function was deprecated in C++17 and removed in C++20 because use_count is only an approximation in multithreaded environment (see Notes in use_count)
可以理解,unique()本质上通过调用use_count()判断引用计数是否为1,而use_count()并不能提供unique()所代表的语义:当前shared_ptr是否为持有对象的唯一持有者。cppreference中std::shared_ptr<T>::use_count()的解释的更为详细:
comparison with 0. If use_count returns zero, the shared pointer is empty and manages no objects (whether or not its stored pointer is null). In multithreaded environment, this does not imply that the destructor of the managed object has completed.
comparison with 1. If use_count returns 1, there are no other owners. (The deprecated member function unique() is provided for this use case.) In multithreaded environment, this does not imply that the object is safe to modify because accesses to the managed object by former shared owners may not have completed, and because new shared owners may be introduced concurrently, such as by std::weak_ptr::lock.
也就是说,由于use_count()大多数的实现方法(比如我使用的gcc)都使用memory_order_relaxed,导致在多线程场景下,会出现如下状况:
结论
std::shared_ptr的unique()方法在C++20中被移除,主要原因是因为其实现方法并不能实现所代表的语义。移除之后,我们仍可以通过在代码中加入形如use_count() == 1的逻辑去判断当前线程是唯一持有对象的线程,前提是我们知晓了它背后的缺陷,并根据实际的应用场景加合适的memory fense或mutex。
一个unique()函数,其实可以引伸出无数多线程编程理论和思想,这些思想可能在我们日常业务编码中用不到,可却随着现代编程方法的演进,实打实的影响着每一位软件开发工程师。笔者作为一个小菜鸟,在此也只是阐述自己的理解,如果不对之处欢迎指教!
参考链接
总结
以上是生活随笔为你收集整理的从C++20 shared_ptr移除unique()方法浅析多线程同步的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: RDMA简介
- 下一篇: C/C++多个链接库含有同名函数,编译会