close
實現單例模式的思路是:一個類別只有一個實例,並提供全域點存取此實例。
有些物件只需要一個實例,比如設定和登入的物件、和驅動程式溝通的物件、執行緒池等,單例模式可以在任何地方存取這個實體,像全域變數一樣方便,且需要時才建立物件,不像全域變數程式一開始就建好物件,造成可能的資源浪費。以下我們示範單例模式的使用,由於一次只會有一個實例產生,所以兩個instance有相同的位址,以下為程式碼。
#include <string>
using namespace std;
class Singleton {
private:
static Singleton *m_instance;
Singleton(){}
public:
static Singleton *getInstance(){
if(m_instance==NULL){
m_instance = new Singleton();
}
return m_instance;
}
};
Singleton* Singleton::m_instance = NULL;
int main(){
Singleton *instance1 = Singleton::getInstance();
Singleton *instance2 = Singleton::getInstance();
int addr1 = (int)instance1;
int addr2 = (int)instance2;
delete instance1;
return 0;
}
單例模式在多執行緒的應用場合下要小心,當唯一實例尚未創建時,如果有兩個執行緒同時調用創建方法,可能各自創建了一個實例,這樣就有兩個實例被構造出來,違反了單例模式的原則,有以下三種解決方式:
1.對getInstance()這個函式同步化,不過會造成程式執行效率降低,如果需要頻繁運作此函式,可能需要重新考慮。
2.率先建立實例,而不用拖延實體化的作法,如以下所示:
class Singleton {
private:
static Singleton *m_instance = new Singleton();
Singleton(){}
public:
static Singleton *getInstance(){
return m_instance;
}
};
3.利用雙重檢查上鎖,在getInstance()中減少使用同步化,檢查實例是否已經建立,沒建立的話才進行同步化,如此一來只有第一次會同步化,如以下所示:
class Singleton {
private:
//volatile不會對m_instance進行編譯器最佳化,確保多執行緒處理m_instance是正確的
volatile static Singleton *m_instance;
Singleton(){}
public:
static Singleton *getInstance(){
if(m_instance==NULL){
//下面進行同步化
m_instance = new Singleton();
}
return m_instance;
}
};
文章標籤
全站熱搜
留言列表