場景:
1. 很多情況下,我們需要實現一個類的單例模式,比如XXManager, 於是提供一個GetInstance()的函數. Java可以使用雙鎖來處理.C/C++也類似.
2. 提供GetInstance()的一個必要條件是必須是線程安全的, 否則會出現創建多個實例的情況. 更簡單的做法是在程序初始化時(Main線程)
調用一個CreateInstance()函數來創建, 但是如果這種單例對象多了的話, 這來CreateInstance調用也會增多, 如果忘記了調用還會直接崩潰.
3. 這裡實現了C/C++ 創建單例模式的方法, 一種是使用pthread庫創建的, 一種是使用win32 api創建.
4. Objc可以使用 dispatch_once來實現單例模式.
+(DhTaskManager*)getInstance { static DhTaskManager *manager = nil; static dispatch_once_t predicate; dispatch_once(&predicate, ^{ manager = [DhTaskManager new]; }); return manager; }
test.cpp
#include#include #include pthread.h #include #include static int THREADCOUNT = 100; class CSLock { public: CSLock() { InitializeCriticalSection(&cs_); std::cout << init lock! << std::endl; } ~CSLock() { DeleteCriticalSection(&cs_); } operator PCRITICAL_SECTION() throw() { return &cs_; } private: CRITICAL_SECTION cs_; }; // 實用場景1: 創建單例對象. class UiDeviceManager { public: static void Destroy() { delete singleton_; } // 1.使用pthread_once來實現單例模式. static UiDeviceManager* GetInstance() { pthread_once(&random_is_initialized,init_instance); return singleton_; } // 1.使用Windows的原子鎖實現單例模式,不需要pthread庫 static UiDeviceManager* GetInstance2() { static LONG done = 0; if (!InterlockedExchangeAdd(&done, 0)) { EnterCriticalSection(cs_lock_); if(!done) { init_instance(); done = 1; } LeaveCriticalSection(cs_lock_); } return singleton_; } private: static pthread_once_t random_is_initialized; static CSLock cs_lock_; static void init_instance () { //測試,Sleep 3 seconds,驗證這個函數只被執行一次. //看有沒有線程進入這裡. //這裡只是測試 Sleep(3000); std::cout << Sleep End << std::endl; static LONG locki_; //1. 這個變量只是測試用. InterlockedExchangeAdd(&locki_,1); assert(locki_ == 1); //只需要new singleton_ = new UiDeviceManager(); } UiDeviceManager() { } static UiDeviceManager* singleton_; }; CSLock UiDeviceManager::cs_lock_; pthread_once_t UiDeviceManager::random_is_initialized = PTHREAD_ONCE_INIT; UiDeviceManager* UiDeviceManager::singleton_ = NULL; static pthread_barrier_t barrier = NULL; void* ThreadFunc(void* data) { for (int i = 0; i < 10000; ++i) { // UiDeviceManager* udm = UiDeviceManager::GetInstance(); UiDeviceManager* udm = UiDeviceManager::GetInstance2(); } pthread_barrier_wait(&barrier); std::cout << ThreadFunc Finish << std::endl; return NULL; } void TestPthreadOnce() { pthread_barrier_init(&barrier,NULL, THREADCOUNT + 1); for (int i = 0; i < THREADCOUNT; ++i) { pthread_t t; pthread_create(&t,NULL,ThreadFunc,NULL); pthread_detach(t); } std::cout << TestPthreadOnce Begin << std::endl; pthread_barrier_wait(&barrier); std::cout << TestPthreadOnce Finish << std::endl; pthread_barrier_destroy(&barrier); UiDeviceManager::Destroy(); } int main(int argc, char const *argv[]) { TestPthreadOnce(); return 0; }
輸出:
init lock! TestPthreadOnce Begin Sleep End ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish TestPthreadOnce Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish ThreadFunc Finish
http://www.douban.com/note/269039110/ 這個其實是有缺陷的!
pthread_once 函數源碼:
int pthread_once (pthread_once_t * once_control, void (*init_routine) (void)) { if (once_control == NULL || init_routine == NULL) { return EINVAL; } if (!InterlockedExchangeAdd((LPLONG)&once_control->done, 0)) /* MBR fence */ { ptw32_mcs_local_node_t node; ptw32_mcs_lock_acquire((ptw32_mcs_lock_t *)&once_control->lock, &node); if (!once_control->done) { #ifdef _MSC_VER #pragma inline_depth(0) #endif pthread_cleanup_push(ptw32_once_on_init_cancel, (void *)&node); (*init_routine)(); pthread_cleanup_pop(0); #ifdef _MSC_VER #pragma inline_depth() #endif once_control->done = PTW32_TRUE; } ptw32_mcs_lock_release(&node); } return 0; } /* pthread_once */