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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++之单例模式

發(fā)布時(shí)間:2024/4/17 c/c++ 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++之单例模式 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1 本篇主要討論下多線程下的單例模式實(shí)現(xiàn):

  首先是 double check 實(shí)現(xiàn)方式: 這種模式可以滿足多線程環(huán)境下,只產(chǎn)生一個(gè)實(shí)例。

template<typename T>class dclsingleton{public:static T& GetInstance(){if(NULL == value_){MutexGuard mg(mutex_);if (NULL == value_){value_ = new T;}}return *value_;}protected:dclsingleton() { std::cout << "dclsingleton constuctor called" << std::endl; }dclsingleton(const dclsingleton &dcl) {}private:static T* value_;static Mutex mutex_;};

?  但是這種實(shí)現(xiàn)存在除bug的隱患, 問題就在: value_ = new T; 上。《程序員的自我修養(yǎng)》上指出:

  這樣的代碼是有問題的,問題的來源在于 cpu 的亂序執(zhí)行。c++里的new 包含了兩步。

  (1)分配內(nèi)存

  (2)調(diào)用構(gòu)造函數(shù)

  所以 value_ = new T;? 實(shí)際上包含了三步:

  (1)分配內(nèi)存

  (2)在分配內(nèi)存的位置上調(diào)用構(gòu)造函數(shù)  

  (3)將內(nèi)存地址賦值給 value_;

  這三步中,(2), (3)兩步是可以顛倒的,也就是說,可能出現(xiàn),先執(zhí)行(3)這是 value_已經(jīng)不為NULL, 當(dāng)出現(xiàn)另一個(gè)對GetInstance的并發(fā)調(diào)用,if 內(nèi)的 value_ != NULL于是返回,但是還沒有調(diào)用構(gòu)造函數(shù)。于是使用這個(gè)指針的時(shí)候,就會(huì)導(dǎo)致崩潰。

  這時(shí)候需要保證(2), (3)的執(zhí)行順序,通常需要加上內(nèi)存屏障,保證一定保證(2)執(zhí)行完以后,再執(zhí)行(3)

  這里我加上了__sync_synchronize(); 后 實(shí)現(xiàn)是這樣的:

  

       static T& GetInstance(){if(NULL == value_){MutexGuard mg(mutex_);if (NULL == value_){T* tmp = static_cast<T*>(operator new (sizeof(T)));new (tmp) T();__sync_synchronize();value_ = tmp;}}return *value_;}

?

    這樣便可以既保證多線程環(huán)境安全,又保證不會(huì)出現(xiàn)上面的問題。

2. 加上內(nèi)存屏障的示例代碼:dcl_single.h

  

#ifndef __DCL_SINGLE_H #define __DCL_SINGLE_H#include <iostream>namespace yl {class Mutex{public:Mutex(){pthread_mutex_init(&mutex_, NULL);}~Mutex(){pthread_mutex_destroy(&mutex_);}public:void Lock(){pthread_mutex_lock(&mutex_);}void UnLock(){pthread_mutex_unlock(&mutex_);}private:pthread_mutex_t mutex_;};class MutexGuard{public:MutexGuard(Mutex& m) : mutex_(m){mutex_.Lock();}~MutexGuard(){mutex_.UnLock();}private:Mutex mutex_;};template<typename T>class dclsingleton{public:static T& GetInstance(){if(NULL == value_){MutexGuard mg(mutex_);if (NULL == value_){T* tmp = static_cast<T*>(operator new (sizeof(T)));new (tmp) T();__sync_synchronize();value_ = tmp;}}return *value_;}protected:dclsingleton() { std::cout << "dclsingleton constuctor called" << std::endl; }dclsingleton(const dclsingleton &dcl) {}private:static T* value_;static Mutex mutex_;};template<typename T>T* dclsingleton<T>::value_ = NULL;template<typename T>Mutex dclsingleton<T>::mutex_; }#endif View Code

?

  singletonTest.cpp

#include "dcl_single.h" #include <iostream>namespace yl {class MgrSg : public dclsingleton<MgrSg>{private:friend class dclsingleton <MgrSg>;MgrSg(){ std::cout << "MgrSg: constructor called" << std::endl; }~MgrSg() { std::cout << "MgrSg: desconstructor called" << std::endl; }public:void print(){std::cout << "print called" << std::endl;}}; }int main(void) {using namespace yl;MgrSg::GetInstance().print();return 0; }

?

3. 還可以用 unix 下的 pthread_once 來實(shí)現(xiàn)單例模式:

  

template <typename T>class MySingleton{public:static T & getInstance(){pthread_once(&ponce_, &MySingleton::init);return *instance;}protected:MySingleton() {}MySingleton(const MySingleton&) {}private:static void init(){instance = new T();}private:static pthread_once_t ponce_;static T *instance;};template<typename T>pthread_once_t MySingleton<T>::ponce_ = PTHREAD_ONCE_INIT;template<typename T>T *MySingleton<T>::instance = nullptr; }

?

4.我自己遇到的就是以上兩種情況,若是希望了解更全面,可參考下邊:

  http://www.cnblogs.com/liyuan989/p/4264889.html

5. 水平有限,望及時(shí)指出錯(cuò)誤。謝謝

  

轉(zhuǎn)載于:https://www.cnblogs.com/newbeeyu/p/6885098.html

與50位技術(shù)專家面對面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的c++之单例模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。