[同時並行][スレッド同期][C/C++単例モード解析を実現]


シーン:
1.多くの場合、XXXmanagerのようなクラスの単一のモードを実現する必要があり、GetInstance()の関数を提供する.Javaはデュアルロックで処理できる.C/C++も同様である.
2.GetInstance()を提供するために必要な条件の1つは、スレッドが安全でなければならないことである、そうでなければ、複数のインスタンスが作成される場合がある.より簡単な方法は、プログラムの初期化時(Mainスレッド)
CreateInstance()関数を呼び出して作成するが、このような単一のオブジェクトが多くなるとCreateInstance呼び出しも多くなり、呼び出しを忘れると直接クラッシュする.
3.ここでは、pthreadライブラリを使用する作成する方法と、win 32 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

5.クラスの静的インスタンスは、プログラムの実行開始時にmainの実行前にロードされるため、一度だけロードすることが保証される、C/C++の静的記憶領域特性を利用する、より簡単な方法がある.2015.12.10
h   
class ARLModuleManager
{
public:

	static ARLModuleManager* GetModuleManager();

private:
	static ARLModuleManager manager_;
	ARLModuleManager(){}
	virtual ~ARLModuleManager();
cpp  :

ARLModuleManager ARLModuleManager::manager_;

ARLModuleManager* ARLModuleManager::GetModuleManager()
{
	return &manager_;
}

参照先:
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 */

完全なプロジェクトのダウンロードアドレス:
http://download.csdn.net/detail/infoworld/9263465