@OnTheWay
注意兩種需要運(yùn)行時初始化的靜態(tài)對象, s和s_。
前者的初始化時機(jī)C++有保證, 但不保證多線程安全。
后者的初始化時機(jī)C++只保證同一翻譯單元內(nèi)中有順序。
再看static CAssistForSingleton m_refSycObj;
這就屬于第2種。
下面的情況有發(fā)生的可能性:
1. 另一翻譯單元的靜態(tài)對象先于m_refSycObj被初始化
2. 在它初始化時訪問了CSingleton *GetInstatnce()
此時就訪問了一個"未初始化"的臨界區(qū)。
這已經(jīng)是bug。
再有, 如果有下列情況:
1. 一些先于m_refSycObj初始化的代碼開啟了線程
2. 多個線程在m_refSycObj初始化前訪問CSingleton *GetInstatnce()
一個未初始化的m_refSycObj根本不能用于同步。
所以, 上面的第1個問題: 這樣做不是多線程安全的。
而靜態(tài)對象在構(gòu)造時啟動線程的情況并不多, 所以并不一定需要將s_作成多線程安全。
例如boost就是這樣, 要求在進(jìn)入main之前, 是不許有兩條以上的執(zhí)行路徑去訪問。
這就是第2個問題。
如果需要完全的多線程安全:
1. 使用once_initial函數(shù)(pthread或者win6有提供)
2. 使用"可以靜態(tài)初始化"的鎖, 比如pthread_mutex_t就可以
或者自己使用一個spinlock也行。
我沒有msn…… 用gmail的同名郵箱。
回復(fù) 更多評論