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的描述:
Executes the???Callable????object???f? ??exactly once, even if called concurrently, from several threads.
In detail:
- If, by the time?
?call_once? ???is called,??flag? ???indicates that??f? ???was already called,??call_once? ???returns right away (such a call to??call_once? ??is known aspassive). - Otherwise, call_once invokes???std::forward??<Callable>(f)with the arguments???std::forward??<Args>(args)...?(as if by??std::invoke???). Unlike the??std::thread????constructor or??std::async???, the arguments are not moved or copied because they don't need to be transferred to another thread of execution. (such a call to?
?call_once? ??is known asactive). - If that invocation throws an exception, it is propagated to the caller of?
?call_once? ??, and the flag is not flipped so that another call will be attempted (such a call to??call_once? ??is known asexceptional). - If that invocation returns normally (such a call to?
?call_once? ??is known asreturning), the flag is flipped, and all other calls to??call_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.
?
|