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