最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解C++實現(xiàn)線程安全的單例模式

 更新時間:2019年03月14日 09:37:21   作者:麻子來了  
這篇文章主要介紹了C++實現(xiàn)線程安全的單例模式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

在某些應用環(huán)境下面,一個類只允許有一個實例,這就是著名的單例模式。單例模式分為懶漢模式,跟餓漢模式兩種。

首先給出餓漢模式的實現(xiàn)

正解:

template <class T>
class singleton
{
protected:
  singleton(){};
private:
  singleton(const singleton&){};//禁止拷貝
  singleton& operator=(const singleton&){};//禁止賦值
  static T* m_instance;
public:
  static T* GetInstance();
};
 
 
template <class T>
T* singleton<T>::GetInstance()
{
  return m_instance;
}
 
template <class T>

在實例化m_instance 變量時,直接調(diào)用類的構(gòu)造函數(shù)。顧名思義,在還未使用變量時,已經(jīng)對m_instance進行賦值,就像很饑餓的感覺。這種模式,在多線程環(huán)境下肯定是線程安全的,因為不存在多線程實例化的問題。

下面來看懶漢模式

template <class T>
class singleton
{
protected:
  singleton(){};
private:
  singleton(const singleton&){};
  singleton& operator=(const singleton&){};
  static T* m_instance;
public:
  static T* GetInstance();
};
 
 
template <class T>
T* singleton<T>::GetInstance()
{
  if( m_instance == NULL)
  { 
    m_instance = new T();
  }
  return m_instance;
}
 
template <class T>
T* singleton<T>::m_instance = NULL;

懶漢模式下,在定義m_instance變量時先等于NULL,在調(diào)用GetInstance()方法時,在判斷是否要賦值。這種模式,并非是線程安全的,因為多個線程同時調(diào)用GetInstance()方法,就可能導致有產(chǎn)生多個實例。要實現(xiàn)線程安全,就必須加鎖。

下面給出改進之后的代碼

template <class T>
class singleton
{
protected:
    singleton(){};
private:
    singleton(const singleton&){};
    singleton& operator=(const singleton&){};
    static T* m_instance;
    static pthread_mutex_t mutex;
public:
    static T* GetInstance();
};
 
 
template <class T>
T* singleton<T>::GetInstance()
{
    pthread_mutex_lock(&mutex);
    if( m_instance == NULL)
    {
        m_instance = new T();
    }
    pthread_mutex_unlock(&mutex);
    return m_instance;
}
 
 
template <class T>
pthread_mutex_t singleton<T>::mutex = PTHREAD_MUTEX_INITIALIZER;
 
template <class T>
T* singleton<T>::m_instance = NULL;

 這一切看起來都很完美,但是程序猿是一種天生就不知道滿足的動物。他們發(fā)現(xiàn)GetInstance()方法,每次進來都要加鎖,會影響效率。然而這并不是必須的,于是又對GetInstance()方法進行改進

template <class T>
T* singleton<T>::GetInstance()
{
  if( m_instance == NULL)
  {
    pthread_mutex_lock(&mutex);
    if( m_instance == NULL)
    { 
       m_instance = new T();
    }
    pthread_mutex_unlock(&mutex);
  }
  return m_instance;
}

這也就是所謂的“雙檢鎖”機制。但是有人質(zhì)疑這種實現(xiàn)還是有問題,在執(zhí)行 m_instance = new T()時,可能 類T還沒有初始化完成,m_instance 就已經(jīng)有值了。這樣會導致另外一個調(diào)用GetInstance()方法的線程,獲取到還未初始化完成的m_instance 指針,如果去使用它,會有意料不到的后果。其實,解決方法也很簡單,用一個局部變量過渡下即可:

正解:

template <class T>
T* singleton<T>::GetInstance()
{
  if( m_instance == NULL)
  {
    pthread_mutex_lock(&mutex);
    if( m_instance == NULL)
    { 
       T* ptmp = new T();
       m_instance = ptmp;
    }
    pthread_mutex_unlock(&mutex);
  }
  return m_instance;
}

到這里在懶漢模式下,也就可以保證線程安全了。

然而,在linux下面還有另一種實現(xiàn)。linux提供了一個叫pthread_once()的函數(shù),它保證在一個進程中,某個函數(shù)只被執(zhí)行一次。下面是使用pthread_once實現(xiàn)的線程安全的懶漢單例模式

template <class T>
class singleton
{
protected:
  singleton(){};
private:
  singleton(const singleton&){};
  singleton& operator=(const singleton&){};
  static T* m_instance;
  static pthread_once_t m_once;
public:
  static void Init();
  static T* GetInstance();
};
 
 
template <class T>
void singleton<T>::Init()
{
  m_instance = new T();
}
 
template <class T>
T* singleton<T>::GetInstance()
{
  pthread_once(&m_once,Init);
  return m_instance;
}
 
template <class T>
pthread_once_t singleton<T>::m_once = PTHREAD_ONCE_INIT;
 
template <class T>
T* singleton<T>::m_instance = NULL;

 上面的單例類使用了模板,對每一種類型的變量都能實例化出唯一的一個實例。

例如要實例化一個int類型

int *p = singleton<int>::GetInstance()

例如要實例化一個string類型

string *p = singleton<string>::GetInstance()

在上面的實現(xiàn)中,在實例化對象時,調(diào)用GetInstance()函數(shù)時都沒有傳遞參數(shù),這是猶豫不同的對象其初始化時參數(shù)個數(shù)都不一樣。如果要支持不同類型的對象帶參數(shù)初始化,則需要重載GetInstance函數(shù)。然而在c++11中,已經(jīng)支持了可變參數(shù)函數(shù)。這里給出一個簡單的例子

#ifndef _SINGLETON_H_
#define _SINGLETON_H_
 
template <class T>
class singleton
{
protected:
  singleton(){};
private:
  singleton(const singleton&){};
  singleton& operator=(const singleton&){};
  static T* m_instance;
public:
  template <typename... Args>
  static T* GetInstance(Args&&... args)
  {
    if(m_instance == NULL)
      m_instance = new T(std::forward<Args>(args)...);
    return m_instance;
  }
 
 
  static void DestroyInstance()
  {
    if(m_instance )
      delete m_instance;
    m_instance = NULL;
  }
};
 
 
template <class T>
T* singleton<T>::m_instance = NULL;
 
#endif

測試函數(shù)

#include <iostream>
#include <string>
#include "singleton.h"
 
using namespace std;
struct A
{
  A(int a ,int b):_a(a),_b(b)
  {}
  int _a;
  int _b;
};
 
int main()
{
  int *p1 = singleton<int>::GetInstance(5);
  int *p2 = singleton<int>::GetInstance(10);
  cout << *p1 << " " << *p2 <<endl;
  string *p3 = singleton<string>::GetInstance("aa");
  string *p4 = singleton<string>::GetInstance("bb");
 
  cout << *p3 << " " << *p4 <<endl;
 
  A *p5 = singleton<A>::GetInstance(1,2);
 
  A *p6 = singleton<A>::GetInstance(4,5);
 
  cout << p5->_a << " " << p6->_a<<endl;
  return 0;
}
 

運行結(jié)果如下

以上所述是小編給大家介紹的C++實現(xiàn)線程安全的單例模式詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • 5分鐘內(nèi)了解C語言的指針

    5分鐘內(nèi)了解C語言的指針

    這篇文章主要介紹了5分鐘內(nèi)了解C語言的指針,本文講解了指針、引用和取值、void指針、NULL指針和未初始化指針、指針和數(shù)組等內(nèi)容,需要的朋友可以參考下
    2015-01-01
  • C語言實現(xiàn)階乘的示例詳解

    C語言實現(xiàn)階乘的示例詳解

    在現(xiàn)實中,我們做數(shù)學題總會遇到階乘問題,這在計算機中也不例外。 那我們應該怎么實現(xiàn)呢?下面小編就為大家講解一下C語言中階乘的實現(xiàn)
    2022-07-07
  • QT5編譯使用QFtp的方法步驟

    QT5編譯使用QFtp的方法步驟

    這篇文章主要介紹了QT5編譯使用QFtp的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • C語言單鏈表實現(xiàn)圖書管理系統(tǒng)

    C語言單鏈表實現(xiàn)圖書管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C語言單鏈表實現(xiàn)圖書管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C++多態(tài)實現(xiàn)方式詳情

    C++多態(tài)實現(xiàn)方式詳情

    這篇文章主要介紹了C++多態(tài)實現(xiàn)方式詳情,多態(tài)是一種面向?qū)ο蟮脑O(shè)計思路,本身和C++不是強綁定的,其他語言當中一樣有多態(tài),只不過實現(xiàn)的方式可能有所不同。下面來一起了解更多詳細內(nèi)容吧
    2022-01-01
  • C++實現(xiàn)洗牌發(fā)牌排序功能的示例代碼

    C++實現(xiàn)洗牌發(fā)牌排序功能的示例代碼

    本篇文章主要介紹了C++實現(xiàn)洗牌發(fā)牌排序功能的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • C++設(shè)計模式之模板方法模式

    C++設(shè)計模式之模板方法模式

    這篇文章主要介紹了C++設(shè)計模式之模板方法模式,本文講解了什么是模板方法模式、模板方法模式的UML類圖、模板方法模式的使用場合等內(nèi)容,需要的朋友可以參考下
    2014-10-10
  • 詳解QML?調(diào)用?C++?中的內(nèi)容

    詳解QML?調(diào)用?C++?中的內(nèi)容

    這篇文章主要介紹了QML?怎么調(diào)用?C++?中的內(nèi)容,這里主要是總結(jié)一下,怎么在 QML 文件中引用 C ++ 文件里定義的內(nèi)容,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-10-10
  • C語言中 & 和 &&的區(qū)別詳解

    C語言中 & 和 &&的區(qū)別詳解

    這篇文章主要介紹了C語言中 & 和 &&的區(qū)別詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • AVX2指令集優(yōu)化整形數(shù)組求和算法

    AVX2指令集優(yōu)化整形數(shù)組求和算法

    這篇文章主要為大家介紹了AVX2指令集優(yōu)化整形數(shù)組求和算法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-05-05

最新評論

崇信县| 荥阳市| 临夏市| 富平县| 清涧县| 桐庐县| 西乡县| 瑞昌市| 莱州市| 广元市| 额尔古纳市| 城市| 奈曼旗| 锦屏县| 本溪市| 同仁县| 汾阳市| 阿克| 保康县| 南木林县| 香格里拉县| 灵台县| 普格县| 大理市| 红桥区| 扎囊县| 绿春县| 宁河县| 灵宝市| 岱山县| 方城县| 财经| 广丰县| 鲁甸县| 墨竹工卡县| 建阳市| 威海市| 观塘区| 晋州市| 资源县| 武定县|