某些场景下,我们需要代码只被执行一次,比如单例类的初始化,考虑到多线程安全,需要进行加锁控制。C++11中提供的call_once可以很好的满足这种需求,使用又非常简单。
头文件#include
template <class Fn, class... Args> void call_once (once_flag& flag, Fn&& fn, Args&&...args);
call_once保证函数fn只被执行一次,如果有多个线程同时执行函数fn调用,则只有一个活动线程(active call)会执行函数,其他的线程在这个线程执行返回之前会处于”passive execution”(被动执行状态)——不会直接返回,直到活动线程对fn调用结束才返回。对于所有调用函数fn的并发线程,数据可见性都是同步的(一致的)。
还有一个要注意的地方是 once_flag的生命周期,它必须要比使用它的线程的生命周期要长。所以通常定义成全局变量比较好。
例子:
#include "stdafx.h" #include <iostream> #include <mutex> #include <Windows.h> int main() { std::once_flag oc; for (int i = 0;i < 5;i++) { std::call_once(oc, [&]() {std::cout << "call once" << std::endl;}); } getchar(); return 0; }
运行结果如下:
可见函数调用了5次,只执行了1次。