1. 程式人生 > >C++單例模式(執行緒安全、記憶體釋放)

C++單例模式(執行緒安全、記憶體釋放)

一、懶漢模式:即第一次呼叫該類例項的時候才產生一個新的該類例項,並在以後僅返回此例項。
需要用鎖,來保證其執行緒安全性:原因:多個執行緒可能進入判斷是否已經存在例項的if語句,從而non thread safety.
使用double-check來保證thread safety.但是如果處理大量資料時,該鎖才成為嚴重的效能瓶頸。
1、靜態成員例項的懶漢模式:

class Singleton  
{  
private:  
    static Singleton* m_instance;  
    Singleton(){}  
public:  
    static Singleton* getInstance();  
};  

Singleton* Singleton::getInstance()  
{  
   if
(NULL == m_instance) { Lock();//借用其它類來實現,如boost if(NULL == m_instance) { m_instance = new Singleton; } UnLock(); } return m_instance; }

2、內部靜態例項的懶漢模式
這裡需要注意的是,C++0X以後,要求編譯器保證內部靜態變數的執行緒安全性,可以不加鎖。但C++ 0X以前,仍需要加鎖。

class SingletonInside  
{  
private
: SingletonInside(){} public: static SingletonInside* getInstance() { Lock(); // not needed after C++0x static SingletonInside instance; UnLock(); // not needed after C++0x return instance; } };

二、餓漢模式:即無論是否呼叫該類的例項,在程式開始時就會產生一個該類的例項,並在以後僅返回此例項。
由靜態初始化例項保證其執行緒安全性,WHY?因為靜態例項初始化在程式開始時進入主函式之前就由主執行緒以單執行緒方式完成了初始化,不必擔心多執行緒問題。
故在效能需求較高時,應使用這種模式,避免頻繁的鎖爭奪。

class SingletonStatic  
{  
private:  
    static const SingletonStatic* m_instance;  
    SingletonStatic(){}  
public:  
    static SingletonStatic* getInstance()  
    {  
        return m_instance;  
    }  
};  

//外部初始化 before invoke main  
const SingletonStatic* SingletonStatic::m_instance = new SingletonStatic;  

m_pInstance指向的空間什麼時候釋放呢?更嚴重的問題是,該例項的解構函式什麼時候執行?

如果在類的析構行為中有必須的操作,比如關閉檔案,釋放外部資源,那麼上面的程式碼無法實現這個要求。我們需要一種方法,正常的刪除該例項。
可以在程式結束時呼叫GetInstance(),並對返回的指標掉用delete操作。這樣做可以實現功能,但不僅很醜陋,而且容易出錯。因為這樣的附加程式碼很容易被忘記,而且也很難保證在delete之後,沒有程式碼再呼叫GetInstance函式。
一個妥善的方法是讓這個類自己知道在合適的時候把自己刪除,或者說把刪除自己的操作掛在作業系統中的某個合適的點上,使其在恰當的時候被自動執行。
我們知道,程式在結束的時候,系統會自動析構所有的全域性變數。事實上,系統也會析構所有的類的靜態成員變數,就像這些靜態成員也是全域性變數一樣。利用這個特徵,我們可以在單例類中定義一個這樣的靜態成員變數,而它的唯一工作就是在解構函式中刪除單例類的例項。如下面的程式碼中的CGarbo類(Garbo意為垃圾工人):

class CSingleton  
{  
//其他成員  
public:  
    static CSingleton* GetInstance();  
private:  
    CSingleton(){};  
    static CSingleton * m_pInstance;  
    class CGarbo //它的唯一工作就是在解構函式中刪除CSingleton的例項  
    {  
    public:  
        ~CGarbo()  
        {  
            if( CSingleton::m_pInstance )  
                delete CSingleton::m_pInstance;  
        }  
}  
    Static CGabor Garbo; //定義一個靜態成員,程式結束時,系統會自動呼叫它的解構函式  
};  

類CGarbo被定義為CSingleton的私有內嵌類,以防該類被在其他地方濫用。
程式執行結束時,系統會呼叫CSingleton的靜態成員Garbo的解構函式,該解構函式會刪除單例的唯一例項。
使用這種方法釋放單例物件有以下特徵:
在單例類內部定義專有的巢狀類;
在單例類內定義私有的專門用於釋放的靜態成員;
利用程式在結束時析構全域性變數的特性,選擇最終的釋放時機;
使用單例的程式碼不需要任何操作,不必關心物件的釋放。
具體程式碼如下:

#include <iostream>>   
using namespace std;  

class Singleton   
{   
public:  
    static Singleton *GetInstance();  
private:  
    Singleton()  
    {  
        cout << "Singleton ctor" << endl;  
    }  
    ~Singleton()  
    {  
        cout << "Singleton dtor" << endl;  
    }  
    static Singleton *m_pInstance;  
    class Garbo  
    {  
    public:  
        ~Garbo()  
        {  
            if (Singleton::m_pInstance)  
            {  
                cout << "Garbo dtor" << endl;  
                delete Singleton::m_pInstance;  
            }  
        }  
    };  
    static Garbo garbo;  
};   
Singleton::Garbo Singleton::garbo;  // 一定要初始化,不然程式結束時不會析構garbo  
Singleton *Singleton::m_pInstance = NULL;  
Singleton *Singleton::GetInstance()  
{  
    if (m_pInstance == NULL)  
        m_pInstance = new Singleton;  
    return m_pInstance;  
}  

int main()  
{  
    Singleton *p1 = Singleton::GetInstance();  
    Singleton *p2 = Singleton::GetInstance();  
    if (p1 == p2)  
        cout << "p1 == p2" << endl;  
    return 0;  
} 

相關推薦

C++模式執行安全記憶體釋放

一、懶漢模式:即第一次呼叫該類例項的時候才產生一個新的該類例項,並在以後僅返回此例項。 需要用鎖,來保證其執行緒安全性:原因:多個執行緒可能進入判斷是否已經存在例項的if語句,從而non thread safety. 使用double-check來保證thr

設計模式模式執行安全

可以說單例模式是所有設計模式中最簡單的一種。 單例模式就是說系統中對於某類的只能有一個物件,不可能出來第二個 單例模式也是23種設計模式中在面試時少數幾個會要求寫程式碼的模式之一。主要考察的是多執行緒下面單例模式的執行緒安全性問題。 1.多執行緒安全單例模式例項

java模式執行安全

package cn.yang.test.controller; /**單例模式 * Created by Dev_yang on 2016/2/26. */ public class Singl

object-c 模式執行安全

單例模式(Singleton Pattern):保證一個類只有一個例項,並且提供一個訪問它的全域性訪問點。 單例在程式設計中是最常見的設計模式之一,下面我們來實現一個單例: Singleton.h 檔案 #import <Foundation/F

C++的模式執行安全模式懶漢/餓漢

單例模式 單例模式:是一種常用的軟體設計模式。在它的核心結構中只包含一個被稱為單例的特殊類。通過單例模式可以保證系統中一個類只有一個例項。即一個類只有一個物件例項。   實現簡單的單例模式:建構函式宣告為private或protect防止被外部函式

python中模式執行安全問題

看了好多文章都是java實現的,特此寫一篇python的。 這個問題的兩種解決方案: 1.最簡單粗暴的就是在系統中先生成一個單例,就不存線上程安全問題了 2.用雙重同步鎖去實現,一把鎖加外面,一把鎖加里面: class Singleton(object): __instance

模式執行安全

package com.day3; public class SingleTonDemo { public static void main(String[] args) { SinleTonThread sinleTonThread=new SinleTonThread();

JAVA設計模式-模式(Singleton)執行安全與效率

一,前言   單例模式詳細大家都已經非常熟悉了,在文章單例模式的八種寫法比較中,對單例模式的概念以及使用場景都做了很不錯的說明。請在閱讀本文之前,閱讀一下這篇文章,因為本文就是按照這篇文章中的八種單例模式進行探索的。   本文的目的是:結合文章中的八種單例模式的寫法,使用實際的示例,來演示執行緒安全和效率  

設計模式模式執行安全問題

前言 單例模式分為“餓漢模式”與“懶漢模式”。今天我們來聊聊單例模式,特別是在多執行緒中我們需要特別注意。 餓漢模式 class Singleton{ private static Singleton singleton = new Singleton(); private Singl

模式執行安全解析

面試的時候,常常會被問到這樣一個問題:請您寫出一個單例模式(Singleton Pattern)吧。     單例的目的是為了保證執行時Singleton類只有唯一的一個例項,最常用的地方比如拿到資料庫的連線,Spring的中建立BeanFactory這些開銷比較大的操作,

java 模式執行安全的餓漢模式和懶漢模式

單例模式 解決的問題:保證一個類在記憶體中的物件唯一性. 比如:多程式讀取一個配置檔案時,建議配置檔案封裝成物件。會方便操作其中資料,又要保證多個程式讀到的是同一個配置檔案物件, 就需要該配置檔案物件在記憶體中是唯一的。 如何保證物件唯一性呢? 思想: 1,不讓其他程式建立

Java五種模式執行安全

單例模式是一種常用的軟體設計模式,常被用於一個類在系統中最多隻允許存在一個例項的場合,如視窗管理器、列印緩衝池、檔案系統等。在單例模式的核心結構中,只包含一個被稱為單例類的特殊類。通過單例模式可以保證系統中一個類只有一個例項而且該例項易於外界訪問,從而方便對例項個數的控制並節約系統資源。如果希望在系統中某個類

C# 基礎十四C#模式:首先介紹 執行執行加鎖 模式。然後介紹模式執行同步:多執行有序訪問共享記憶體

一、簡介 本篇文章將介紹如何使用單例模式,也就是類的例項化,在整個專案的生命週期內,只例項化一次。在單例模式中,往往可以看到如SourceCode.cs:這樣的結構的。 SourceCode.cs: public class Singleton { private static

模式餓漢式 執行安全記憶體洩露

// Singleton.cpp : 定義控制檯應用程式的入口點。 //通過巢狀類實現析構 #include "stdafx.h" #include <iostream>     using namespace std; class Singleton{ pr

懶漢式模式為何執行安全

這裡是一個懶漢式的示例程式碼:public class Singleton { private static Singleton s; private Singleton() { } public static Singleton getInstance

解決多執行模式執行安全問題

DCL雙檢查鎖機制 public class MyConfig { private volatile static MyConfig myConfig = null;//volatile

Spring bean 和bean的執行安全

Bean的作用域    Spring 3中為Bean定義了5中作用域,分別為singleton(單例)、prototype(原型)、request、session和global session,5種作用域說明如下: singleton:單例模式,Spring I

模式執行

單例模式的多執行緒         比如使用者點選   程式正在操作這條資料的過程中  然後又有一個人點選  又把這條資料修改了  多執行緒會發生的問題 這時候 當第一個使用者點選後&nbs

個人單子模式學習筆記執行安全雙重檢查Volitale

單子模式我已經栽了兩次了,第一次是單子模式沒有考慮執行緒安全,第二次被問到double check 和Volitale。鬼知道下一次我又栽在單子模式的哪兒,所以我決定,見到什麼問題,就都在這兒記著了。 我們先看這種雙重檢查,不加volatile public stat

列舉實現原理:執行安全及發序列化依舊為原因

單例的列舉實現在《Effective Java》中有提到,因為其功能完整、使用簡潔、無償地提供了序列化機制、在面對複雜的序列化或者反射攻擊時仍然可以絕對防止多次例項化等優點,單元素的列舉型別被作者認為是實現Singleton的最佳方法。 其實現非常簡單,如下: