**
僅僅是學習設計模式而不用於實際,很快會忘記。從專案中學習處理複雜問題的方法,將之總結為設計模式才是正道。
某些情況下,我需要某個類只被例項化一次,用了一次就不能再被例項化。
這樣的類就叫做單例類。
私有化建構函式 ------- 保證不能隨意的建立類物件
私有化乙個靜態成員變數 -------- 做有沒有例項化過的標誌,保證只例項化一次
公開的靜態成員函式介面 ------ 建立類物件的介面
#include
#include
#include
#include
#include
#include
using
namespace std;
//單例類 只能生成乙個物件
class
mycas
static mycas* s_instance;
//靜態成員變數
public
://靜態成員函式介面
static mycas*
getinstance()
return s_instance;
}void
func()
};//初始化靜態變數
mycas* mycas::s_instance =
null
;void
test01()
intmain()
在公開的靜態介面內建立物件的模式為懶漢式模式,還可以把建立物件寫在類外(餓漢式),後一種保證了之後無論是不是多執行緒,無論怎麼訪問。靜態介面都只會返回靜態變數,實際用起來再看看。
餓漢式:
class
mycas
static mycas* s_instance;
//靜態成員變數
public
://靜態成員函式介面
static mycas*
getinstance()
void
func()
};//初始化靜態變數
mycas* mycas::s_instance =
newmycas()
;
如果想自己釋放單例類的靜態變數的記憶體,千萬不要寫下面這樣的成員方法:
static
void
freespace()
}
一般使用單例都是在多執行緒中使用的,如果在一邊被釋放,另一邊還要用就會產生問題了。
所以,不要手動釋放單例的記憶體。
如果想釋放,需要憑藉巢狀類可以訪問類中私有變數的方法:
在單例類中寫乙個巢狀類,宣告定義乙個巢狀類的靜態變數--------這個變數的生命週期會一直到程式退出時--------當程式退出,巢狀類的析構被執行到,在析構中把單例的靜態變數記憶體刪除。
class
garbo}}
;
將下面這個隨便寫在單例類**。
static garbo garbo;
多執行緒中使用單例模式的示例**:
#include
#include
#include
#include
#include
#include
using
namespace std;
//單例類 只能生成乙個物件
class
mycas
static mycas* s_instance;
//靜態成員變數
public
://靜態成員函式介面
static mycas*
getinstance()
return s_instance;
}/*巢狀類*/
class
cgarrelease}}
;/*巢狀類完*/
void
func()
};//初始化靜態變數
mycas* mycas::s_instance =
null
;//執行緒入口函式
void
myprint()
/*共享資料分析
1.單例初始化一般在建立執行緒之前
2.多執行緒需要讀寫單例時,需要在子執行緒中建立單例類物件
*/void
test02()
intmain()
為了提高程式效率,不能總是使用一次getinstance()就給執行緒加一把鎖,而是只在第一次建立類物件時有加鎖。
解決方案是在加鎖前,再判斷一次!!!
static mycas*
getinstance()
}return s_instance;
}
第乙個條件判斷的意思是,某個執行緒例項化後,其他執行緒和此執行緒都不應該再進入了。
那麼為什麼裡面還要再判斷一次呢?
第二個條件判斷的意思是,第一次例項化時,好幾個執行緒一同進入加鎖的位置,如果沒有第二個條件,那麼就不能避免重複建立類物件。
std::call_once()類模板 第二個引數是函式名a
功能:保證函式a只被呼叫一次
特徵:具備互斥量的能力
使用方式:和std::once_flag()這個標記配合使用
std::call_flag()呼叫成功後,標記std::once_flag就會被設定為「已呼叫」狀態,那麼函式a就不會執行了。
#include
#include
#include
#include
#include
#include
using
namespace std;
mutex resource_mutex;
std::once_flag g_flag;
//系統定義的標記
//單例類 只能生成乙個物件
class
mycas
private
://私有化建構函式
mycas()
static mycas* s_instance;
//靜態成員變數
public
://靜態成員函式介面
static mycas*
getinstance()
return s_instance;
}/*巢狀類*/
class
cgarrelease}}
;/*巢狀類完*/
void
func()
};//初始化靜態變數
mycas* mycas::s_instance =
null
;//執行緒入口函式
void
myprint()
void
test02()
intmain()
1.函式a為std::call_once()所使用到的函式(呼叫自身)
#include
#include
#include
using
namespace std;
std::once_flag g_flag;
void
do_once1()
);}void
test01()
呼叫自身使用的是lambda表示式,也可以寫成下面這樣:
void
do_once1()
; std::
call_once
(g_flag,my_lambda)
;}
2.函式a內還有std::call_once()呼叫函式b
#include
#include
#include
using
namespace std;
std::once_flag g_flag;
inline
void
may_throw_function
(bool do_throw)
cout <<
"once\n";}
inline
void
do_once
(bool do_throw)
//catch(...)
}void
test02()
intmain()
多執行緒 多執行緒 單例設計模式
多執行緒之 單例設計模式 餓漢式 多執行緒安全 1 餓漢式 class single static single getinstance public void show class a implements runnable class test catch interruptedexceptio...
單例設計模式下的多執行緒資料共享 C
include include include using namespace std mutex resource mutex 增加互斥量 once flag g flag 系統定義的標記 較實用的單例類 class mycas private static mycas m instance 靜態...
c 多執行緒單例模式 C 設計模式之單例模式
單例模式 乙個類在記憶體中只有乙個物件 例項 並且提供乙個可以全域性訪問或者獲取這個物件的方法。這兩天學的,寫了個小例子,問了同事一些關於執行緒的問題,還有從網上查了一些資料。還犯了一些低階的錯誤。vs2017控制台輸出文字亂碼,從網上找了一些方法不管用,最後發現是自己新建專案選錯模板了,選擇了.n...