青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

#ant

The dreams in which I'm dying are the best I've ever had...

非完美C++ Singleton實現(xiàn)[2]

4.解決多線程問題
上一篇實現(xiàn)的Singleton只能在單線程環(huán)境中使用,在多線程環(huán)境中會出現(xiàn)很多問題,看Instance()實現(xiàn)代碼:
1?static?Singleton&?Instance()?{
2?????if?(0?==?_instance)?{?//1

3?????????_instance?=?new?Singleton();?//2
4?????????atexit(Destroy);
5?
????}
6?????return?*_instance;?//3

7?}
考慮如下情況:線程一調(diào)用Instance(),進(jìn)入//1,0 == _instance 返回true,線程一于是進(jìn)入//2。這時候線程一被掛起,線程二開始執(zhí)行,線程二調(diào)用Instance(),進(jìn)入//1,發(fā)現(xiàn)0 == _instance 仍然返回true,線程二于是也進(jìn)入//2,線程二繼續(xù)執(zhí)行到//3直到返回。這時候線程一被喚醒,繼續(xù)從//2開始執(zhí)行,這將會覆蓋線程二創(chuàng)建的_instance,線程一繼續(xù)執(zhí)行到//3直到返回...

解決方法很簡單,引入相關(guān)同步對象(synchronization object)就行了,例如在win32平臺下可以如下實現(xiàn):
synobj.h
?1?#ifndef?SYNOBJ_H
?2?
#define?SYNOBJ_H
?3?

?4?#include?<windows.h>
?5?
?6?#define?CLASS_UNCOPYABLE(classname)?\
?7?????private
:?\
?8?????classname(const?classname&
);?\
?9?????classname&?operator=(const?classname&
);
10?

11?class?Mutex?{
12?
????CLASS_UNCOPYABLE(Mutex)
13?public
:
14?????Mutex()?:_cs()?{?InitializeCriticalSection(&
_cs);?}
15?????~Mutex()?{?DeleteCriticalSection(&
_cs);?}
16?????void?lock()?{?EnterCriticalSection(&
_cs);?}
17?????void?unlock()?{?LeaveCriticalSection(&
_cs);?}
18?private
:
19?
????CRITICAL_SECTION?_cs;
20?
};
21?

22?class?Lock?{
23?
????CLASS_UNCOPYABLE(Lock)
24?public
:
25?????explicit?Lock(Mutex&
?cs)?:_cs(cs)?{?_cs.lock();?}
26?????~
Lock()?{?_cs.unlock();?}
27?private
:
28?????Mutex&
?_cs;
29?
};
30?

31?#endif/*SYNOBJ_H*/

有了同步對象很容易就能夠?qū)懗鋈缦麓a:
singleton.h
?1?#ifndef?SINGLETON_H
?2?
#define?SINGLETON_H
?3?

?4?#include?"synobj.h"
?5?
?6?class?Singleton?{
?7?public
:
?8?????static?Singleton&?Instance()?{?//?Unique?point?of?access

?9?????????Lock?lock(_mutex);
10?????????if?(0?==
?_instance)?{
11?????????????_instance?=?new
?Singleton();
12?????????????atexit(Destroy);?//?Register?Destroy?function

13?????????}
14?????????return?*
_instance;
15?
????}
16?????void
?DoSomething(){}
17?private
:
18?????static?void?Destroy()?{?//?Destroy?the?only?instance

19?????????if?(?_instance?!=?0?)?{
20?
????????????delete?_instance;
21?????????????_instance?=?0
;
22?
????????}
23?
????}
24?????Singleton(){}?//?Prevent?clients?from?creating?a?new?Singleton

25?????~Singleton(){}?//?Prevent?clients?from?deleting?a?Singleton
26?????Singleton(const?Singleton&);?//?Prevent?clients?from?copying?a?Singleton
27?????Singleton&?operator=(const?Singleton&);
28?private
:
29?????static
?Mutex?_mutex;
30?????static?Singleton?*_instance;?//?The?one?and?only?instance

31?};
32?

33?#endif/*SINGLETON_H*/

singleton.cpp
1?#include?"singleton.h"
2?
3?Mutex?Singleton::_mutex;
4?Singleton*?Singleton::_instance?=?0;
現(xiàn)在的Singleton雖然多線程安全,性能卻受到了影響。從Instance()中可以看到,實際上僅僅當(dāng)0 == _instance為true時才需要Lock。你很容易就寫出如下代碼:
1?static?Singleton&?Instance()?{
2?????if?(0?==
?_instance)?{
3?
????????Lock?lock(_mutex);
4?????????_instance?=?new
?Singleton();
5?
????????atexit(Destroy);
6?
????}
7?????return?*
_instance;
8?}
但是這樣還是會產(chǎn)生競爭條件(race condition),一種廣為人知的做法是使用所謂的Double-Checked Locking:
?1?static?Singleton&?Instance()?{
?2?????if?(0?==
?_instance)?{
?3?
????????Lock?lock(_mutex);
?4?????????if?(0?==
?_instance)?{
?5?????????????_instance?=?new
?Singleton();
?6?
????????????atexit(Destroy);
?7?
????????}
?8?
????}
?9?????return?*
_instance;
10?}
Double-Checked Locking機制看起來像是一個完美的解決方案,但是在某些條件下仍然不行。簡單的說,編譯器為了效率可能會重排指令的執(zhí)行順序(compiler-based reorderings)。看這一行代碼:

_instance?=?new?Singleton();

在編譯器未優(yōu)化的情況下順序如下:
1.new operator分配適當(dāng)?shù)膬?nèi)存;
2.在分配的內(nèi)存上構(gòu)造Singleton對象;
3.內(nèi)存地址賦值給_instance。


但是當(dāng)編譯器優(yōu)化后執(zhí)行順序可能如下:
1.new operator分配適當(dāng)?shù)膬?nèi)存;
2.內(nèi)存地址賦值給_instance;
3.在分配的內(nèi)存上構(gòu)造Singleton對象。


當(dāng)編譯器優(yōu)化后,如果線程一執(zhí)行到2后被掛起。線程二開始執(zhí)行并發(fā)現(xiàn)0 == _instance為false,于是直接return,而這時Singleton對象可能還未構(gòu)造完成,后果...

上面說的還只是單處理器的情況,在多處理器(multiprocessors)的情況下,超線程技術(shù)必然會混合執(zhí)行指令,指令的執(zhí)行順序更無法保障。關(guān)于Double-Checked Locking的更詳細(xì)的文章,請看:
The "Double-Checked Locking is Broken" Declaration

5.使用volatile關(guān)鍵字
為了說明問題,請先考慮如下代碼:
?1?class?MyThread?:?public?Thread?{
?2?public
:
?3?????virtual?void
?run()?{
?4?????????while?(!
_stopped)?{
?5?????????????//do?something

?6?????????}
?7?
????}
?8?????void
?stop()?{
?9?????????_stopped?=?true
;
10?
????}
11?private
:
12?
????bool?_stopped;
13?
};
14?

15?...
16?
17?MyThread?thread;
18?thread.start();
上面用thread.start()開啟了一個線程,該線程在while循環(huán)中檢測bool標(biāo)記_stopped,看是否該繼續(xù)執(zhí)行。如果想要結(jié)束這個線程,調(diào)用thread.stop()應(yīng)該沒問題。但是需要注意的是編譯器很有可能對_stopped的存取進(jìn)行優(yōu)化。如果編譯器發(fā)現(xiàn)_stopped被頻繁存取(_stopped在while循環(huán)中),編譯器可能會考慮將_stopped緩存到寄存器中,以后_stopped將會直接從寄存器存取。這時候如果某個線程調(diào)用了thread.stop(),對_stopped的修改將不會反映到寄存器中,thread將會永遠(yuǎn)循環(huán)下去...

為了防止編譯器優(yōu)化,用volatile關(guān)鍵字就OK了,volatile跟const的用法幾乎一樣,能用const的地方也都能用volatile。對Singleton來說,修改如下兩處即可:
1?//singleton.h中
2?static?Singleton?*_instance;
3?//改為

4?static?Singleton?*?volatile?_instance;
5?

6?//singleton.cpp中
7?Singleton*?Singleton::_instance?=?0;
8?//改為

9?Singleton*?volatile?Singleton::_instance?=?0;


6.將Singleton泛化為模板
singleton.h
?1?#ifndef?SINGLETON_H
?2?
#define?SINGLETON_H
?3?

?4?#include?"synobj.h"
?5?
?6?template<class?T>
?7?class?Singleton?{
?8?
????CLASS_UNCOPYABLE(Singleton)
?9?public
:
10?????static?T&?Instance()?{?//?Unique?point?of?access

11?????????if?(0?==?_instance)?{
12?
????????????Lock?lock(_mutex);
13?????????????if?(0?==
?_instance)?{
14?????????????????_instance?=?new
?T();
15?
????????????????atexit(Destroy);
16?
????????????}
17?
????????}
18?????????return?*
_instance;
19?
????}
20?protected
:
21?
????Singleton(){}
22?????~
Singleton(){}
23?private
:
24?????static?void?Destroy()?{?//?Destroy?the?only?instance

25?????????if?(?_instance?!=?0?)?{
26?
????????????delete?_instance;
27?????????????_instance?=?0
;
28?
????????}
29?
????}
30?????static
?Mutex?_mutex;
31?????static?T?*?volatile?_instance;?//?The?one?and?only?instance

32?};
33?

34?template<class?T>
35?Mutex?Singleton<T>::_mutex;
36?

37?template<class?T>
38?T?*?volatile?Singleton<T>::_instance?=?0;
39?

40?#endif/*SINGLETON_H*/

測試代碼:
test.cpp
?1?#include?"singleton.h"
?2?
?3?class?A?:?public?Singleton<A>?{
?4?????friend?class?Singleton<A>
;
?5?protected
:
?6?
????A(){}
?7?????~
A(){}
?8?public
:
?9?????void
?DoSomething(){}
10?
};
11?

12?int?main()?{
13?

14?????A?&a?=?A::Instance();
15?
????a.DoSomething();
16?

17?????return?0;
18?}


7.Singleton的析構(gòu)問題
到此Singleton已經(jīng)算比較完善了,但是依然算不上完美,因為到現(xiàn)在只是解決了多線程問題,加入了模板支持,對于KDL problem(The Dead Reference Problem)依然沒法解決,可以說在實現(xiàn)Singleton模式時,最大的問題就是多個有依賴關(guān)系的Singleton的析構(gòu)順序。雖然Modern C++ Design中給出了解決方案,但是Loki的實現(xiàn)太過復(fù)雜,在此就不詳細(xì)說明了,有興趣的可以看看Modern C++ Design,當(dāng)然了,Loki庫中用策略模式實現(xiàn)的Singleton也很不錯!

posted on 2007-09-07 23:22 螞蟻終結(jié)者 閱讀(5088) 評論(13)  編輯 收藏 引用 所屬分類: Design Pattern

Feedback

# re: 非完美C++ Singleton實現(xiàn)[2] 2007-09-08 09:12 sneaker

"The Dead Reference Problem"確實是實現(xiàn)Singleton的首要問題  回復(fù)  更多評論   

# re: 非完美C++ Singleton實現(xiàn)[2] 2007-09-09 03:25 func

華麗的推演,“裱”成PDF收藏~期待下篇  回復(fù)  更多評論   

# re: 非完美C++ Singleton實現(xiàn)[2] 2007-09-10 11:14 ChenA

volatile也解決不了多線程的問題,詳情請看C++ and the Perils of Double-Checked Locking。
KDL的問題設(shè)計成不依賴不就行了,需要依賴關(guān)系的手動釋放,這是最簡單的辦法。  回復(fù)  更多評論   

# re: 非完美C++ Singleton實現(xiàn)[2] 2007-09-10 11:33 螞蟻終結(jié)者

@ChenA
thanks!  回復(fù)  更多評論   

# re: 非完美C++ Singleton實現(xiàn)[2] 2007-09-19 14:24 func

我的理解,volatile雖然不能解決多線程的很多問題,但這里的使用應(yīng)該解決了問題.  回復(fù)  更多評論   

# re: 非完美C++ Singleton實現(xiàn)[2] 2007-10-09 14:33 fr3@K

已知 : global (static) instance 在 multithreading 下有啟始上的問題。
試問 : 如何用一個 global instance (mutex) 去確保另一個 global instance 的啟始正確?

請參考拙著 Is your Singleton Broken? (http://fsfoundry.org/codefreak/2006/05/05/is-your-singleton-broken/)  回復(fù)  更多評論   

# re: 非完美C++ Singleton實現(xiàn)[2] 2007-10-09 16:30 螞蟻終結(jié)者

@fr3@K
實際上multithreading的問題不在于mutex這里,一個好的設(shè)計會在main函數(shù)真正啟動后再調(diào)用Instance(),而這時候global object可以確保已經(jīng)初始化,即在調(diào)用Instance()時可以保證mutex已經(jīng)初始化。因此只要程序在真正進(jìn)入main函數(shù)以前不調(diào)用Instance(),就不會有g(shù)lobal instance的初始化問題。  回復(fù)  更多評論   

# re: 非完美C++ Singleton實現(xiàn)[2] 2007-10-09 16:32 螞蟻終結(jié)者

其實后來覺得多數(shù)情況下eager initialization要優(yōu)于lazy initialization。
如經(jīng)典的Meyer's Singleton以及Boost::singleton
  回復(fù)  更多評論   

# re: 非完美C++ Singleton實現(xiàn)[2] 2007-10-09 16:42 王博煒

強  回復(fù)  更多評論   

# re: 非完美C++ Singleton實現(xiàn)[2] 2007-10-09 21:00 fr3@K

@螞蟻終結(jié)者

我的考量多是站在 library writer (職業(yè)病) 的角度。
Library 常需要在程式一 load 上來就把 static (global) instance 啟始好. 總不好要求使用者進(jìn)入 main() 才能使用.

希望你能把進(jìn)入 main() 之后再呼叫 Instance() 這段加入你的文章里面, 以免誤導(dǎo)了讀者如我輩.

我是盡量避免 lazy initialization 的人, 尤其是在 static instance (singleton) 的創(chuàng)建上. Lazy initialization 的策略有可能造成譬如說一個 global logger 在某個對象的虛構(gòu)函數(shù)內(nèi)第一次被使用 (或許可能性很小, 但畢竟不能 100% 排除), 而我們又無法保證該 logger 肯定會被創(chuàng)建成功. 這樣是否代表我們必須在每個使用到 logger 的 destructor 內(nèi)部做 try-and-catch? 等等問題...  回復(fù)  更多評論   

# re: 非完美C++ Singleton實現(xiàn)[2] 2007-10-10 09:06 螞蟻終結(jié)者

@fr3@K
謝謝你的建議。
不能從static code中調(diào)用Instance()確實是一種限制。我想應(yīng)該可以通過某種類似Boost::singleton中的技巧來確保static object(mutex)在Instance()之前初始化。有時間了再把這段內(nèi)容補上。  回復(fù)  更多評論   

# re: 非完美C++ Singleton實現(xiàn)[2] 2008-05-06 09:21 sodar

非常好的文章,學(xué)習(xí)了

可是遇到一個問題,如果我是在動態(tài)庫工程中使用這個Singleton,因為atexit不能用于DLL,這種實現(xiàn)是不是會有問題呢?  回復(fù)  更多評論   

# re: 非完美C++ Singleton實現(xiàn)[2] 2008-05-06 22:02 螞蟻終結(jié)者

@sodar
能說下在動態(tài)庫工程中使用Singleton的具體需求嗎?dll中用atexit注冊的函數(shù)在FreeLibrary的時候會被調(diào)用,可以保證Singleton安全析構(gòu)。  回復(fù)  更多評論   

# re: 非完美C++ Singleton實現(xiàn)[2] 2012-05-28 08:26 SYBILRobbins

This is known that cash can make us autonomous. But what to do when somebody does not have money? The only one way is to try to get the <a href="http://goodfinance-blog.com/topics/business-loans">business loans</a> and financial loan.   回復(fù)  更多評論   

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            99精品视频网| 在线 亚洲欧美在线综合一区| 国产精品扒开腿做爽爽爽视频| 美腿丝袜亚洲色图| 麻豆精品传媒视频| 欧美激情一区| 国产精品99一区| 国产精品专区一| 国内精品一区二区| 日韩一二三区视频| 欧美一二三视频| 免费看成人av| 亚洲天堂av图片| 久久频这里精品99香蕉| 欧美色精品在线视频| 久久精品国产精品亚洲精品| 嫩草影视亚洲| 国产精品乱看| 亚洲国产合集| 久久爱www久久做| 欧美激情一二区| 亚洲一卡二卡三卡四卡五卡| 可以免费看不卡的av网站| 欧美日韩精品久久久| 国产一区高清视频| 亚洲一区区二区| 欧美mv日韩mv国产网站| 日韩视频在线一区二区| 久久久噜噜噜久久人人看| 欧美天堂亚洲电影院在线观看 | 久久三级视频| 欧美午夜剧场| 亚洲国产精品欧美一二99| 亚洲欧美视频在线观看| 欧美激情精品久久久久久黑人| 亚洲一级二级| 欧美精品v日韩精品v国产精品| 国产一区二区黄| 亚洲一区成人| 久久亚洲风情| 99国产精品久久久久久久| 亚洲男人的天堂在线观看| 亚洲欧美一区二区精品久久久| 久久国产精品99国产精| 亚洲毛片视频| 久久精品日产第一区二区| 欧美日韩一区二| 亚洲高清一区二区三区| 久久人人97超碰人人澡爱香蕉| 一本色道久久加勒比精品| 欧美国产日本| 亚洲国产一区视频| 久久综合一区二区| 亚洲男女自偷自拍图片另类| 欧美日韩国产成人| 亚洲精品美女久久7777777| 久久永久免费| 久久精品99国产精品日本| 国产一区二区三区四区老人| 欧美影院精品一区| 亚欧美中日韩视频| 韩国精品久久久999| 久久深夜福利| 久久一区免费| 亚洲精品专区| 亚洲免费观看高清完整版在线观看熊 | 亚洲欧洲另类国产综合| 久久精品国产第一区二区三区| 国产精品有限公司| 先锋影音久久久| 午夜精品久久| 一色屋精品视频在线看| 欧美成人一区二区在线| 欧美精品www| 亚洲综合国产| 久久疯狂做爰流白浆xx| 亚洲精品久久视频| av成人免费| 国产无一区二区| 欧美国产日韩精品| 欧美日韩一二三区| 性感少妇一区| 久久这里有精品视频| 日韩一区二区电影网| 亚洲一卡久久| 亚洲欧洲精品成人久久奇米网| 亚洲精品一区二| 国产日韩精品在线播放| 亚洲成人中文| 国产精品美女www爽爽爽| 麻豆精品在线播放| 欧美日本韩国一区二区三区| 欧美日韩性生活视频| 欧美一级视频免费在线观看| 久久理论片午夜琪琪电影网| 一区二区三区国产盗摄| 午夜在线不卡| 一区二区欧美国产| 久久久亚洲国产天美传媒修理工| 亚洲视频1区| 久久久精品999| 午夜视频一区二区| 欧美精品久久一区二区| 狼人社综合社区| 国产精品国产馆在线真实露脸| 美女久久网站| 国产亚洲免费的视频看| 99精品国产在热久久婷婷| 亚洲黄色免费电影| 午夜亚洲福利在线老司机| 亚洲午夜视频在线| 鲁大师成人一区二区三区| 久久国产主播| 国产精品护士白丝一区av| 亚洲国产精品传媒在线观看 | 女人天堂亚洲aⅴ在线观看| 性欧美1819sex性高清| 欧美大片91| 免费观看国产成人| 韩国福利一区| 小黄鸭精品密入口导航| 亚洲一区二区在线免费观看| 欧美日韩成人综合| 亚洲国产精品久久精品怡红院| 一区二区在线不卡| 欧美尤物一区| 欧美中文字幕不卡| 国产精品视频区| 亚洲一区高清| 午夜视频在线观看一区二区| 国产精品av一区二区| 一区二区欧美亚洲| 亚洲欧美成人一区二区三区| 国产精品成人观看视频国产奇米| 日韩亚洲一区在线播放| 亚洲视频你懂的| 欧美性猛交视频| 亚洲一区二区三区在线观看视频| 亚洲图片你懂的| 欧美性久久久| 亚洲男人第一av网站| 欧美在线中文字幕| 黄网动漫久久久| 久久亚洲国产精品一区二区| 女仆av观看一区| 亚洲人成人一区二区三区| 欧美国产日本高清在线| 99xxxx成人网| 校园激情久久| 一区二区在线视频播放| 欧美成人免费网站| 日韩一区二区高清| 欧美一区二区三区精品| 国产一区二区三区直播精品电影| 久久久高清一区二区三区| 欧美激情视频在线播放| 亚洲少妇一区| 国产精品一区视频网站| 久久尤物电影视频在线观看| 亚洲欧洲三级电影| 欧美精品在欧美一区二区少妇| 一本色道久久综合狠狠躁篇的优点| 欧美与黑人午夜性猛交久久久| 国外成人在线| 欧美极品在线播放| 欧美一区二区成人6969| 亚洲国产婷婷香蕉久久久久久| 亚洲一区二区在线视频| 国产自产在线视频一区| 欧美精品三级| 久久精品国产成人| 亚洲久久一区| 久久亚洲春色中文字幕| 亚洲图片欧美日产| 黄色一区二区在线| 国产精品都在这里| 看片网站欧美日韩| 亚洲欧美电影院| 亚洲精品三级| 免费看亚洲片| 欧美专区福利在线| 亚洲视频在线观看网站| 亚洲国产精品电影在线观看| 国产精品日本欧美一区二区三区| 免费成人黄色| 欧美一区二区在线| 制服丝袜激情欧洲亚洲| 欧美激情一区二区三区高清视频 | 欧美日韩少妇| 久久综合色综合88| 欧美亚洲尤物久久| 在线综合+亚洲+欧美中文字幕| 欧美成年人在线观看| 久久国产直播| 性伦欧美刺激片在线观看| 一区二区三区日韩精品| 亚洲精品日韩欧美| 亚洲国产精品成人| 国内精品久久久久影院优| 国产视频精品免费播放|