日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++中各种智能指针的实现及弊端(四)

發布時間:2024/4/11 c/c++ 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++中各种智能指针的实现及弊端(四) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C++中各種智能指針的實現及弊端(四)

文章目錄

    • C++中各種智能指針的實現及弊端(四)
    • 一、std::shared_ptr
    • 二、std::shared_ptr的線程安全問題:

一、std::shared_ptr

std::shared_ptr文檔

int main() {// shared_ptr通過引用計數支持智能指針對象的拷貝shared_ptr<Date> sp(new Date);shared_ptr<Date> copy(sp);cout << "ref count:" << sp.use_count() << endl;cout << "ref count:" << copy.use_count() << endl;return 0; }
  • shared_ptr的原理:是通過引用計數的方式來實現多個shared_ptr對象之間共享資源。例如:
  • shared_ptr在其內部,給每個資源都維護了著一份計數,用來記錄該份資源被幾個對象共享。
  • 在對象被銷毀時(也就是析構函數調用),就說明自己不使用該資源了,對象的引用計數減一。
  • 如果引用計數是0,就說明自己是最后一個使用該資源的對象,必須釋放該資源;
  • 如果不是0,就說明除了自己還有其他對象在使用該份資源,不能釋放該資源,否則其他對象就成野指
    針了
  • 詳細請參考:引用計數+淺拷貝=解決淺拷貝

    // 模擬實現一份簡答的SharedPtr,了解原理 #include <thread> #include <mutex> template <class T> class SharedPtr { public:SharedPtr(T* ptr = nullptr): _ptr(ptr), _pRefCount(new int(1)), _pMutex(new mutex){}~SharedPtr() {Release();}SharedPtr(const SharedPtr<T>& sp): _ptr(sp._ptr), _pRefCount(sp._pRefCount), _pMutex(sp._pMutex){AddRefCount();}// sp1 = sp2SharedPtr<T>& operator=(const SharedPtr<T>& sp){//if (this != &sp)if (_ptr != sp._ptr){// 釋放管理的舊資源Release();// 共享管理新對象的資源,并增加引用計數_ptr = sp._ptr;_pRefCount = sp._pRefCount;_pMutex = sp._pMutex;AddRefCount();}return *this;}T& operator*() {return *_ptr;}T* operator->() {return _ptr;}int UseCount() {return *_pRefCount;}T* Get() { return _ptr; }void AddRefCount(){// 加鎖或者使用加1的原子操作_pMutex->lock();++(*_pRefCount);_pMutex->unlock();} private:void Release(){bool deleteflag = false;// 引用計數減1,如果減到0,則釋放資源_pMutex.lock();if (--(*_pRefCount) == 0){delete _ptr;delete _pRefCount;deleteflag = true;}_pMutex.unlock();if(deleteflag == true)delete _pMutex;}private:int* _pRefCount; // 引用計數T* _ptr; // 指向管理資源的指針mutex* _pMutex; // 互斥鎖 };int main() {SharedPtr<int> sp1(new int(10));SharedPtr<int> sp2(sp1);*sp2 = 20;cout << sp1.UseCount() << endl;cout << sp2.UseCount() << endl;SharedPtr<int> sp3(new int(10));sp2 = sp3;cout << sp1.UseCount() << endl;cout << sp2.UseCount() << endl;cout << sp3.UseCount() << endl;sp1 = sp3;cout << sp1.UseCount() << endl;cout << sp2.UseCount() << endl;cout << sp3.UseCount() << endl; return 0; }

    上面的代碼采用加鎖的方式;主要是為了:防止計數_pRefCount出現錯亂問題

    二、std::shared_ptr的線程安全問題:

    通過下面的程序我們來測試shared_ptr的線程安全問題。需要注意的是shared_ptr的線程安全分為兩方面:

    1. 智能指針對象中引用計數是多個智能指針對象共享的,兩個線程中智能指針的引用計數同時++或–,這個操作不是原子的,引用計數原來是1,++了兩次,可能還是2.這樣引用計數就錯亂了。會導致資源未釋放或者程序崩潰的問題。所以只能指針中引用計數++、–是需要加鎖的,也就是說引用計數的操作是線程安全的。

    2. 智能指針管理的對象存放在堆上,兩個線程中同時去訪問,會導致線程安全問題。

    // 1.演示引用計數線程安全問題,就把AddRefCount和SubRefCount中的鎖去掉 // 2.演示可能不出現線程安全問題,因為線程安全問題是偶現性問題,main函數的n改大 //一些概率就變大了,就容易出現了。 // 3.下面代碼我們使用SharedPtr演示,是為了方便演示引用計數的線程安全問題, //將代碼中的SharedPtr換成shared_ptr進行測試,可以驗證庫的shared_ptr, //發現結論是一樣的。void SharePtrFunc(SharedPtr<Date>& sp, size_t n) {cout << sp.Get() << endl;for (size_t i = 0; i < n; ++i){// 這里智能指針拷貝會++計數,智能指針析構會--計數,這里是線程安全的。SharedPtr<Date> copy(sp);// 這里智能指針訪問管理的資源,不是線程安全的。所以我們看看這些值兩個線程++了2n次,但是最//終看到的結果,并一定是加了2ncopy->_year++;copy->_month++;copy->_day++;} }int main() {SharedPtr<Date> p(new Date);cout << p.Get() << endl;const size_t n = 100;thread t1(SharePtrFunc, p, n);thread t2(SharePtrFunc, p, n);t1.join();t2.join();cout << p->_year << endl;cout << p->_month << endl;cout << p->_day << endl;return 0; }

    通過上面的代碼驗證了如果把AddRefCount和SubRefCount中的鎖去掉,可能會造成線程安全問題;

    因為線程是搶占式執行的,那個線程先訪問計數_pRefCount是不確定的,所以就可能會造成計數_pRefCount錯亂,不是線程安全的。

    但是上面的代碼還是有問題的:存在循環引用問題;
    解決方法:解決循環引用問題

    總結

    以上是生活随笔為你收集整理的C++中各种智能指针的实现及弊端(四)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。