C++11中的std::call_once
2017-04-30 16:50
316 查看
某些场景下,我们需要代码只被执行一次,比如单例类的初始化,考虑到多线程安全,需要进行加锁控制。C++11中提供的call_once可以很好的满足这种需求,使用又非常简单。
头文件#include<mutex>
template <class Fn, class... Args>
void call_once (once_flag& flag, Fn&& fn, Args&&...args);
第一个参数是std::once_flag的对象(once_flag是不允许修改的,其拷贝构造函数和operator=函数都声明为delete),第二个参数可调用实体,即要求只执行一次的代码,后面可变参数是其参数列表。
call_once保证函数fn只被执行一次,如果有多个线程同时执行函数fn调用,则只有一个活动线程(active call)会执行函数,其他的线程在这个线程执行返回之前会处于”passive execution”(被动执行状态)——不会直接返回,直到活动线程对fn调用结束才返回。对于所有调用函数fn的并发线程,数据可见性都是同步的(一致的)。
如果活动线程在执行fn时抛出异常,则会从处于”passive execution”状态的线程中挑一个线程成为活动线程继续执行fn,依此类推。一旦活动线程返回,所有”passive execution”状态的线程也返回,不会成为活动线程。(实际上once_flag相当于一个锁,使用它的线程都会在上面等待,只有一个线程允许执行。如果该线程抛出异常,那么从等待中的线程中选择一个,重复上面的流程)。
static std::once_flag oc; // 用于call_once的局部静态变量
Singleton* Singleton::m_instance;
Singleton* Singleton::getInstance() {
std::call_once(oc, [&] () { m_instance = newSingleton(); });
return m_instance;
}
还有一个要注意的地方是 once_flag的生命周期,它必须要比使用它的线程的生命周期要长。所以通常定义成全局变量比较好。
头文件#include<mutex>
template <class Fn, class... Args>
void call_once (once_flag& flag, Fn&& fn, Args&&...args);
第一个参数是std::once_flag的对象(once_flag是不允许修改的,其拷贝构造函数和operator=函数都声明为delete),第二个参数可调用实体,即要求只执行一次的代码,后面可变参数是其参数列表。
call_once保证函数fn只被执行一次,如果有多个线程同时执行函数fn调用,则只有一个活动线程(active call)会执行函数,其他的线程在这个线程执行返回之前会处于”passive execution”(被动执行状态)——不会直接返回,直到活动线程对fn调用结束才返回。对于所有调用函数fn的并发线程,数据可见性都是同步的(一致的)。
如果活动线程在执行fn时抛出异常,则会从处于”passive execution”状态的线程中挑一个线程成为活动线程继续执行fn,依此类推。一旦活动线程返回,所有”passive execution”状态的线程也返回,不会成为活动线程。(实际上once_flag相当于一个锁,使用它的线程都会在上面等待,只有一个线程允许执行。如果该线程抛出异常,那么从等待中的线程中选择一个,重复上面的流程)。
static std::once_flag oc; // 用于call_once的局部静态变量
Singleton* Singleton::m_instance;
Singleton* Singleton::getInstance() {
std::call_once(oc, [&] () { m_instance = newSingleton(); });
return m_instance;
}
还有一个要注意的地方是 once_flag的生命周期,它必须要比使用它的线程的生命周期要长。所以通常定义成全局变量比较好。
相关文章推荐
- c++11 Using Callable Objects, std::thread, std::bind, std::async, std::call_once
- C++11: std::call_once和std::one_flag
- C++11多线程中std::call_once的使用
- C++11多线程编程 call_once
- c++11 call_once用法(多线程时仅初始化一次的完美解决方案)
- [精] C++11中once_flag,call_once实现分析
- C++11中once_flag,call_once实现
- C++11中once_flag,call_once实现分析
- c++11 call_once 使用方法
- C++11于once_flag,call_once分析的实现
- std::call_once
- C++11 std::chrono库详解
- C++11 std::function用法
- c++11的std::memory_order
- C++11中的std::function
- call to OpenGL ES API with no current context (logged once per thread)可能会导致加载问题?
- C++11新特性,利用std::chrono精简传统获取系统时间的方法
- C++11 并发指南四(<future> 详解三 std::future & std::shared_future)(转)
- C++11之std::bind
- -std=c++11