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

歡迎訪問 生活随笔!

生活随笔

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

c/c++

线程安全的单例模式C++实现

發布時間:2023/12/10 c/c++ 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 线程安全的单例模式C++实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

單例模式的介紹

單例模式的優點是只有一個對象,可以節省資源,提高運行速度,提供一個全局的訪問點。
在使用過程中,寫一個具有單例模式思想的程序可以很簡單,但是如果要做到線程安全并且生成實例的過程中符合業務需求,是一件困難的事情。

Lazy mode(懶漢模式)

懶漢模式,會將實例化的時間延遲到正式調用接口的時候。
簡單的實現方式

class singleton { public:singleton* getInstance(){if(p_singletonIns == nullptr){p_singletonIns = new singleton(); }return p_singletonIns; }private:singleton()=default;singleton(const singleton &cpSingleton) = delete;singleton& operator=(const singleton& cpSingleton) = delete;static singleton* p_singletonIns; };singleton* singleton::p_singletonIns = nullptr;

上面的用例中,可以看到上面的p_singletonIns的在第一次調用getInstance()的時候會將p_singletonIns賦予一個實例的地址。這種延遲到使用時才進行實例化的做法,叫做懶漢模式。
但是這種方法不是線程安全的,同時會存在內存泄露的問題。
使用指針的方式的話,在創建實例的時候一般使用DCL(Double Check Lock), 雙檢測鎖。代碼如下所示

class singleton { public:singleton* getInstance(){if(p_singletonIns == nullptr) // p1{std::lock_guard<std::mutex> lock();if(p_singletonIns == nullptr) // p2{p_singletonIns = new singleton(); // p3}}return p_singletonIns;}private:singleton()=default;singleton(const singleton &cpSingleton) = delete;singleton& operator=(const singleton& cpSingleton) = delete;static singleton* p_singletonIns; };singleton* singleton::p_singletonIns = nullptr;

但是在使用過程中, p1的判斷是存在一個風險,線程仍然不安全。就是在p3在new的時候,在new這個過程中,p_singletonIns的指針會被先賦值,然后開始創建內存。在并發的情況下,p1可能判斷出p_singletonIns不是空指針,但是內存其實沒有完全分配完成,那么造成返回p_singletonIns這個指針其實是不可用的。

使用原子變量的懶漢模式

在C++11的標準庫中有原子變量的實現。使用原子變量就可以上述這種避免線程不安全的問題。

std::mutex mutexIns; class singleton { public: static singleton* getInstance() {if(p_singletonIns.load() == nullptr) // p1{std::lock_guard<std::mutex> lock(mutexIns);if(p_singletonIns.load() == nullptr) // p2{p_singletonIns.store(new singleton()); // p3}}return p_singletonIns.load(); }private:singleton()=default;singleton(const singleton &cpSingleton) = delete;singleton& operator=(const singleton& cpSingleton) = delete;static std::atomic<singleton*> p_singletonIns; }; std::atomic<singleton*> singleton::p_singletonIns(nullptr);

使用局部靜態變量的懶漢模式

使用局部靜態變量也可以實現懶漢模式,使用局部靜態變量在C++11之后是線程安全。這也是最為優雅的一種方式。

class singleton { public:static singleton* getInstance(){singleton singletonIns;return &singletonIns;}private:singleton()=default;singleton(const singleton &cpSingleton) = delete;const singleton& operator=(const singleton& cpSingleton) = delete; };

餓漢模式

餓漢模式:故名思意,一個餓壞的人會將一切能吃的東西都塞到肚子里,吃不下去的也要拽在手里。
在編程中這種模式的體現就在于資源在程序啟動的時候就會分配好。而不是在運行時才進行資源分配。
使用餓漢模式編寫單例模式相對簡單一些。

class singleton { public:singleton* getInstance(){return &singletonIns;}private:singleton()=default;singleton(const singleton &cpSingleton) = delete;singleton& operator=(const singleton& cpSingleton) = delete;static singleton singletonIns; }; singleton singleton::singletonIns;

使用餓漢模式的話,singletonIns在C++中進行初始化的過程發生在程序加載的過程中,在main運行之前,也在調用getInstance()之前。這個初始化的過程也可以知道是確保線程安全的。同時也可以保證在程序結束之后自動析構。

關于資源泄露

首先資源泄露并不只是意味著內存泄露,還會指網絡資源的釋放,比如在分布式系統中,在程序退出時,讓其他系統知道程序的退出等等場景。
在單例模式中,因為使用全局變量或者靜態變量進行構造的時候,在程序退出時,會自動進行析構,通常是不存在資源泄漏的。在使用new的情況下,則不會自動進行析構,會存在資源泄漏的問題。下面介紹使用堆內存來構造單例模式的時候,如何在程序推出時,自動析構。

使用靜態的嵌套對象來進行釋放

使用嵌套的對象變量來釋放,是因為單例模式的析構函數是private權限的,因此要使用嵌套對象來解決這個private的訪問權限的問題。也滿足高內聚編程原則。

std::mutex mutexIns; class singleton { public: class deletor { public:~deletor(){singleton *singletonIns;if((singletonIns = getInstance()) != nullptr){delete singletonIns;}} };static singleton* getInstance() {if(p_singletonIns.load() == nullptr) // p1{std::lock_guard<std::mutex> lock(mutexIns);if(p_singletonIns.load() == nullptr) // p2{p_singletonIns.store(new singleton()); // p3}}return p_singletonIns.load(); }private:singleton()=default;singleton(const singleton &cpSingleton) = delete;singleton& operator=(const singleton& cpSingleton) = delete;~singleton(){//do anything to make sure you have prevented resource leak.//...}static std::atomic<singleton*> p_singletonIns;static deletor deletorIns; }; std::atomic<singleton*> singleton::p_singletonIns(nullptr); singleton::deletor deletorIns;

總結

以上是生活随笔為你收集整理的线程安全的单例模式C++实现的全部內容,希望文章能夠幫你解決所遇到的問題。

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