call_once是c++11中引入的新特性,用於保證某個函數只調用一次,即便是多線程環境下,它也能夠可靠地完成一次函數調用。特別適用於某個初始化只執行一次的場景。css
下面代碼是在win7+vs2015編譯器測試經過,演示瞭如何使用c++11 中的call_once方法ios
#include "stdafx.h"
#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>
//單利模式應用
class CSinglton
{
private:
//(1)私有額構造函數
CSinglton() {}
//在析構函數中釋放實例對象
~CSinglton()
{
if (pInstance != NULL)
{
delete pInstance;
pInstance = NULL;
}
}
public:
//(3)得到本類實例的惟一全局訪問點
static CSinglton* GetInstance()
{
//若實例不存在,則嘗試建立實例對象
if (NULL == pInstance)
{
//call_once object makes sure calling CreateInstance function only one time;
//it will be safe without lock;
try
{
std::call_once(m_flag, CreateInstance);
}
catch (...)
{
std::cout << "CreateInstance error\n";
}
}
//實例已經存在,直接該實例對象
return pInstance;
}
static void CreateInstance()
{
pInstance = new(std::nothrow) CSinglton();//分配失敗,是返回NULL;
if (NULL == pInstance)
{
throw std::exception();
}
}
private:
static CSinglton* pInstance;//(2)惟一實例對象
static std::once_flag m_flag;
};
CSinglton* CSinglton::pInstance = NULL;
//構造 once_flag 對象,內部狀態被設爲指示函數仍未被調用。
std::once_flag CSinglton::m_flag;
//輔助測試代碼
std::mutex g_mutex;
void PrintInstanceAddr()
{
std::this_thread::sleep_for(std::chrono::microseconds(1));
//get instance
CSinglton* pIns = CSinglton::GetInstance();
//print instance addr
std::lock_guard<std::mutex> lock(g_mutex);
std::cout << pIns << std::endl;
}
int main()
{
std::thread td[5];
//multhread get instance addr;
for (int i = 0; i < 5; i++)
{
td[i] = std::thread(PrintInstanceAddr);
}
for (int i = 0; i < 5; i++)
{
td[i].join();
}
return 0;
}
運行結果:c++
0076E778 0076E778 0076E778 0076E778 0076E778
參考資料:
http://zh.cppreference.com/w/cpp/thread/call_once
http://www.cplusplus.com/reference/mutex/call_once/?kw=call_oncemarkdown