版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、線程安全的單例模式、/、刖旨單例模式(SingletonPattern)是最簡單的、也是我們很常用的一種設(shè)計模式。保證一個類僅有一個實例,并提供一個該實例的全局訪問點。那么在多線程的環(huán)境,怎么才能更好的確保線程安全呢?實現(xiàn)1餓.漢模式餓漢模式使用一個靜態(tài)成員變量,程序啟動即完成構(gòu)造,不用考慮線程安全的問題,C+11中static的特性:如果當變量在初始化的時候,并發(fā)同時進入聲明語句,并發(fā)線程將會阻塞等待初始化結(jié)束。classSingletonpublic:staticSingleton*GetInstance()returninstance_;if(instance_!=nullptr)del
2、eteinstance_;private:Singleton()=default;Singleton&operator=(constSingleton&)=delete;Singleton(constSingleton&singleton2)=delete;private:staticSingleton*instance_;_intmain()Singleton*s1=Singleton:GetInstance();Singleton:DestreyInstance();return0;關(guān)于資源的釋放上例中我們使用了一個靜態(tài)的成員函數(shù)來釋放堆上的資源,需要手動調(diào)用,并不是很方便。我們可以使用智
3、能指針或者一個內(nèi)部類來實現(xiàn)資源的自動釋放,也更符合Moderncpp的風格。接下來我們演示如何使用一個內(nèi)部類來優(yōu)化餓漢模式。classSingletonpublic:staticSingleton*GetInstance()returninstance_;if(instance_!=nullptr)deleteinstance_;private:classGCpublic:GC()可以在這里銷毀所有的資源,例如:b連接、文件句柄等if(instance_!=nullptr)deleteinstance_;instance_=nullptr;staticGCgc;p!:Singleton()=d
4、efault;Singleton&operator=(constSingleton&)=delete;Singleton(constSingleton&singleton2)=delete;private:staticSingleton*instance_;_懶漢模式餓漢方式不論是否需要使用該對象都將其定義出來,可能浪費了內(nèi)存,或者減慢了程序的啟動速度。所以使用懶漢模式進行優(yōu)化,懶漢模式即延遲構(gòu)造對象,在第一次使用該對象的時候才進行new該對象。而懶漢模式會存在線程安全問題,最出名的解決方案就是Double-CheckedLockingPattern(DCLP)(雙檢鎖)。使用兩次判斷來解決線
5、程安全問題并且提高效率。classSingletonpublic:staticSingleton&GetInstance()if(instance_=nullptr)std:lock_guardlock(mutex_);if(instance_=nullptr)instance_.reset(newSingleton);return*instance_;Singleton()=default;private:Singleton()=default;Singleton(constSingleton&)=delete;Singleton&operator=(constSingleton&)=del
6、ete;private:staticstd:unique_ptrinstance_;staticstd:mutexmutex_;std:unique_ptrSingleton:instance_;std:mutexSingleton:mutex_;雙檢鎖的問題DCLP實際上也是存在這嚴重的線程安全問題的,具體參考原文中有這樣一段話:Consideragainthelinethatinitializespinstanee:pInstance=newSingleton;Thisstatementcausesthreethingstohappen:Step1:Allocatememorytohold
7、aSingletonobject.Step2:ConstructaSingletonobjectintheallocatedmemory.Step3:Makepinstaneepointtotheallocatedmemory.Ofcriticalimportanceistheobservationthatcompilersarenotconstrainedtoperformthesestepsinthisorder!Inparticular,compilersaresometimesallowedtoswapsteps2and3.Whytheymightwanttodothatisaques
8、tionwelladdressinamoment.Fornow,letsfocusonwhathappensiftheydo.也就是我們在instance_=newSingleton;時發(fā)生了三件事情:申請一塊內(nèi)存來保存單例對象。在申請的內(nèi)存中調(diào)用構(gòu)造函數(shù)。將內(nèi)存的地址賦值給instance_。不同的編譯器表現(xiàn)不一樣,它們并不會嚴格按照這個順序執(zhí)行,尤其是有時候允許交換第二步和第三步!也就是說可能會先將內(nèi)存地址賦值給instance_然后再調(diào)用構(gòu)造函數(shù)。這樣就會有嚴重的線程安全問題,比如:線程A剛好申請完內(nèi)存并將該內(nèi)存地址賦值給instance_但是此時還沒調(diào)用構(gòu)造函數(shù),又剛好此時線程B執(zhí)行到
9、了if(instance_=nullptr)判斷instance_并不為空,返回了該變量,然后調(diào)用了該對象的函數(shù),但是該對象還沒進行構(gòu)造。其實就是編譯優(yōu)化導致的一個亂序(reorder)的問題。懶漢模式進一步優(yōu)化1.使用std:call_oneeC+11中std:call_once和std:once_flag配合使用使得函數(shù)可以線程安全的只調(diào)用一次。classSingletonpublic:staticSingleton&GetInstance()staticstd:once_flags_flag;std:call_once(s_flag,&()instance_.reset(newSingl
10、eton););return*instance_;Singleton()=default;voidPrintAddress()conststd:coutthisstd:endl;private:Singleton()=default;Singleton(constSingleton&)=delete;Singleton&operator=(constSingleton&)=delete;private:staticstd:unique_ptrinstance_;std:unique_ptrSingleton:instance_;.使用內(nèi)存屏障classSingletonpublic:stati
11、cSingleton*GetInstance()Singleton*tmp=instance_oad(std:memory_order_relaxed);獲取內(nèi)存屏障std:atomic_thread_fence(std:memory_order_acquire);if(tmp=nullptr)std:lock_guardlock(mutex_);tmp=instance_oad(std:memory_order_relaxed);if(tmp=nullptr)tmp=newSingleton;釋放內(nèi)存屏障std:atomic_thread_fence(std:memory_order_rel
12、ease);instance_store(tmp,std:memory_order_relaxed);atexit(Destructor);returntmp;private:staticvoidDestructor()Singleton*tmp=instance_.load(std:memory_order_relaxed);if(nullptr!=tmp)deletetmp;Singleton()=default;Singleton(constSingleton&)Singleton&operator=(constSingleton&)staticstd:atomicinstance_;s
13、taticstd:mutexmutex_;std:atomicSingleton:instance_;std:mutexSingleton:mutex_;最簡單實用的方式好了,說了這么多,前面一頓操作猛如虎,其實最簡單實用的還是靜態(tài)局部變量的方式。classSingletonpublic:Singleton()staticSingleton&GetInstance()staticSingletoninstance;returninstance;private:Singleton()=default;Singleton(constSingleton&)Singleton&operator=(co
14、nstSingleton&);優(yōu)點:“代碼簡潔;“利用靜態(tài)局部變量特性,延遲加載;“利用靜態(tài)局部變量特性,系統(tǒng)自動回收內(nèi)存,自動調(diào)用析構(gòu)函數(shù);“靜態(tài)局部變量初始化時,沒有new操作帶來的cpu指令reorder操作;“c+11靜態(tài)局部變量初始化時,具備線程安全;升級為模板templatevtypenameTclassSingletonpublic:staticT&GetInstance()staticTinstance;returninstance;protected:virtualSingleton()Singleton()Singleton(constSingleton&)Singleton&operator=(constSingleton&);使用方式比如我們有一個普通類DesignPattern,它是全局唯一的,
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 回熱器產(chǎn)業(yè)鏈招商引資的調(diào)研報告
- 電動高爾夫球車市場分析及投資價值研究報告
- 回聲測深設(shè)備產(chǎn)業(yè)鏈招商引資的調(diào)研報告
- 化學品加工用蒸燙機產(chǎn)業(yè)鏈招商引資的調(diào)研報告
- 安排和組織專家討論會行業(yè)經(jīng)營分析報告
- 不透明度監(jiān)測器產(chǎn)業(yè)鏈招商引資的調(diào)研報告
- 場所的專業(yè)清潔服務行業(yè)相關(guān)項目經(jīng)營管理報告
- 云零售服務行業(yè)相關(guān)項目經(jīng)營管理報告
- 臨床診斷服務行業(yè)相關(guān)項目經(jīng)營管理報告
- 建筑物填縫服務行業(yè)市場調(diào)研分析報告
- 安徽省合肥市第五十中學西校區(qū)2024-2025學年期中考試七年級數(shù)學試題(無答案)
- 社區(qū)計劃生育自查報告(3篇)
- 人教版小學數(shù)學六年級上冊第二單元《位置與方向》單元集體備課整體設(shè)計
- 2024年銀行考試-建設(shè)銀行紀檢監(jiān)察條線考試近5年真題集錦(頻考類試題)帶答案
- 南京六校聯(lián)合體2025屆高三上期10月聯(lián)考英語試題卷(含答案)
- 提升餐飲服務質(zhì)量
- 九年級語文上冊第一單元大單元教學設(shè)計
- 廣東省廣州市2024-2025學年上學期八年級數(shù)學期中復習試卷
- 20世紀時尚流行文化智慧樹知到期末考試答案2024年
- 第四章-國防動員
- 第一講軍事思想概論
評論
0/150
提交評論