c++11 call_once 使用方法
call_once是c++11中引入的新特性,用于保证某个函数只调用一次,即使是多线程环境下,它也可以可靠地完成一次函数调用。特别适用于某个初始化只执行一次的场景。
- 若调用call_once一切顺利,将会翻转once_flag变量的内部状态,再次调用该函数时,所对应的目标函数不会被执行。
- 若调用call_once中发生异常,不会翻转once_flag变量的内部状态,再次调用该函数时,目标函数仍然尝试执行。
下面代码是在win7+vs2015编译器测试通过,演示了如何使用c++11 中的call_once方法
#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;
}
运行结果:
0076E778
0076E778
0076E778
0076E778
0076E778
参考资料:
http://zh.cppreference.com/w/cpp/thread/call_once
http://www.cplusplus.com/reference/mutex/call_once/?kw=call_once