std:call_once是C++11引入的新特性,如需使用,只需要#include <mutex>即可,简单来说std:call_once的作用,确保函数或代码片段在多线程环境下,只需要执行一次,常用的场景如Init()操作或一些系统参数的获取等。
相对来说,std::call_once用法比较简单,配合std::once_flag即可实现,废话不多说,上代码:
#include "stdafx.h" #include <iostream> #include <thread> #include <mutex> std::once_flag flag; void Initialize() { std::cout << "Run into Initialize.." << std::endl; } void Init() { std::call_once(flag, Initialize); } int main() { std::thread t1(Init); std::thread t2(Init); std::thread t3(Init); std::thread t4(Init); t1.join(); t2.join(); t3.join(); t4.join(); }
执行结果如下:
可以看到,Initialize()只调用了一次。
需要了解更多的话,可以参考https://en.cppreference.com/w/cpp/thread/call_once关于std::call_once的描述:
Executesthe Callable object f exactly once, even if called concurrently, from several threads.
In detail:
● If, by the timecall_once is called,flag indicates thatf was already called,call_once returns right away (such a call tocall_once is known aspassive).
● Otherwise, call_once invokes std::forward<Callable>(f)with the arguments std::forward<Args>(args)... (as if bystd::invoke). Unlike thestd::thread constructor orstd::async, the arguments are not moved or copied because they don't need to be transferred to another thread of execution. (such a call tocall_once is known asactive).
● If that invocation throws an exception, it is propagated to the caller ofcall_once, and the flag is not flipped so that another call will be attempted (such a call tocall_once is known asexceptional).
● If that invocation returns normally (such a call tocall_once is known asreturning), the flag is flipped, and all other calls tocall_once with the same flag are guaranteed to bepassive.
All active calls on the same flag form a single total order consisting of zero or more exceptional calls, followed by one returning call. The end of each active call synchronizes-with the next active call in that order.
The return from the returning call synchronizes-with the returns from all passive calls on the same flag: this means that all concurrent calls to call_once are guaranteed to observe any side-effects made by the active call, with no additional synchronization.