从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++多个链接库含有同名函数,编译会