c 多執行緒單例模式 C 單例模式實現

2021-10-14 01:29:19 字數 2015 閱讀 4072

單例模式,可以說設計模式中最常應用的一種模式了。但是如果沒有學過設計模式的人,可能不會想到要去應用單例模式,面對單例模式適用的情況,可能會優先考慮使用全域性或者靜態變數的方式,這樣比較簡單,也是沒學過設計模式的人所能想到的最簡單的方式了。

一般情況下,我們建立的一些類是屬於工具性質的,基本不用儲存太多的跟自身有關的資料,在這種情況下,每次都去new乙個物件,即增加了開銷,也使得**更加臃腫。其實,我們只需要乙個例項物件就可以。如果採用全域性或者靜態變數的方式,會影響封裝性,特別對於大型專案,很容易照成名字衝突。基於這些原因,大佬們設計出了單例模式。

在實現的時候,我們將類的建構函式設定為private,這樣,外部就不會去構造該類的物件了,只能通過我們提供的函式來獲取。

在單執行緒環境下,我們會這麼實現:

class csingleton ;
最為核心的是getinstance()函式,在單執行緒下, 實現是:

csingleton* csingleton::_instance = null;  csingleton* csingleton::getinstance()   return _instance; }
在多執行緒環境下,上述函式getinstance在多個執行緒執行時會存在競爭,例如兩個執行緒都判斷_instance == null 為true,都會new乙個新物件。這明顯會有問題。因此需要加鎖保護。對於多執行緒而言,getinstance函式通常如下實現:

csingleton* csingleton::getinstance()   unlock();  return _instance; }
這個函式看起來解決了問題,但是每當執行緒getinstance()時,都要先lock,其實我們只在一開始建立乙個例項,因此後續每次_instance == null判斷結果都是false,從而返回_instance,這其實會導致很多無效的lock,unlock(對於linux下的mutex來說,這兩個動作還是很昂貴的,每次都lock,unlock都快失去單例模式的優勢了),基於這個問題,引出了double check機制。如下:

csingleton* csingleton::getinstance()   unlock();  }  return _instance; }
這時,只是在首次呼叫的時候呼叫了lock,unlock後續由於每次判斷_instance == null都為false,因此直接返回_instance。

但是這樣完美了嗎?這段**看起來沒有問題,當函式返回時,_instance總是指向乙個有效物件。為lock和unlock又解決了多執行緒競爭的問題。

但是實際上這個**也有問題。問題的**是cpu的亂序執行。c++裡,new包含了兩個步驟:

這時, _instance = new csingleton()就包含了三步:

在這三步中,2和3步完全可以顛倒。也就會出現如下情況: _instance不為null,但是沒有呼叫建構函式。這時如果另外乙個執行緒直接呼叫getinstance,就會直接得到乙個沒有構造完全的物件。這時候程式會如何執行就不得而知了。

可見,cpu的亂序執行對於多執行緒保障有了很大挑戰。因此,要保證多執行緒安全,在某些時候必須阻止cpu換序。通常會呼叫cpu的一條指令(比較遺憾,不同的平台,通常不同),該指令通常被稱為barrier。barrier會阻止cpu將barrier之前和之後的指令交換。由此得到執行緒安全的實現。:

csingleton* csingleton::getinstance()   unlock();  }  return _instance; }
由於barrier的存在,物件的構造一定在barrier之前完成,因此,當_instance被賦值時物件總是構造好的。如此就實現了多執行緒環境下的單例模式。

先看簡單的實現,對於c++11,由於c++11中可以保證static變數時多執行緒安全的,在底層實現了加鎖操作,所以不需要像以前那樣自己寫加鎖操作,因此實現如下:

class singleton};

c 多執行緒單例模式 執行緒安全C 單例模式

我對此處記錄的單例模式有一些疑問 http us library ff650316.aspx 以下 摘自該文章 using system public sealed class singleton private static volatile singleton instance private ...

c 多執行緒單例模式 C 設計模式之單例模式

單例模式 乙個類在記憶體中只有乙個物件 例項 並且提供乙個可以全域性訪問或者獲取這個物件的方法。這兩天學的,寫了個小例子,問了同事一些關於執行緒的問題,還有從網上查了一些資料。還犯了一些低階的錯誤。vs2017控制台輸出文字亂碼,從網上找了一些方法不管用,最後發現是自己新建專案選錯模板了,選擇了.n...

多執行緒 單例模式

單例模式 是非常典型常用的一種設計模式 乙份資源只能被申 載一次 單例模式的方法建立的類在當前程序中只有乙個例項 資源的程式初始化的時候就去載入,後面使用的時候直接使用,使用的時候比較流暢,有可能會載入用不上的資源,導致程式初始化時間比較慢。include class single instance...