C++11特性之std:call_once介绍

简介: std:call_once是C++11引入的新特性,如需使用,只需要#include <mutex>即可,简单来说std:call_once的作用,确保函数或代码片段在多线程环境下,只需要执行一次,常用的场景如Init()操作或一些系统参数的获取等。

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();
}

执行结果如下:

169926d9ecf746c3952394465621b190.png

可以看到,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.

相关文章
|
1月前
|
编译器 程序员 定位技术
C++ 20新特性之Concepts
在C++ 20之前,我们在编写泛型代码时,模板参数的约束往往通过复杂的SFINAE(Substitution Failure Is Not An Error)策略或繁琐的Traits类来实现。这不仅难以阅读,也非常容易出错,导致很多程序员在提及泛型编程时,总是心有余悸、脊背发凉。 在没有引入Concepts之前,我们只能依靠经验和技巧来解读编译器给出的错误信息,很容易陷入“类型迷路”。这就好比在没有GPS导航的年代,我们依靠复杂的地图和模糊的方向指示去一个陌生的地点,很容易迷路。而Concepts的引入,就像是给C++的模板系统安装了一个GPS导航仪
103 59
|
1月前
|
存储 编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(三)
【C++】面向对象编程的三大特性:深入解析多态机制
|
1月前
|
存储 编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(二)
【C++】面向对象编程的三大特性:深入解析多态机制
|
1月前
|
编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(一)
【C++】面向对象编程的三大特性:深入解析多态机制
|
1月前
|
存储 安全 编译器
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(一)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
|
26天前
|
C++
C++ 20新特性之结构化绑定
在C++ 20出现之前,当我们需要访问一个结构体或类的多个成员时,通常使用.或->操作符。对于复杂的数据结构,这种访问方式往往会显得冗长,也难以理解。C++ 20中引入的结构化绑定允许我们直接从一个聚合类型(比如:tuple、struct、class等)中提取出多个成员,并为它们分别命名。这一特性大大简化了对复杂数据结构的访问方式,使代码更加清晰、易读。
32 0
|
1月前
|
存储 编译器 C++
【C++】面向对象编程的三大特性:深入解析继承机制(三)
【C++】面向对象编程的三大特性:深入解析继承机制
|
1月前
|
编译器 C++
【C++】面向对象编程的三大特性:深入解析继承机制(二)
【C++】面向对象编程的三大特性:深入解析继承机制
|
1月前
|
安全 程序员 编译器
【C++】面向对象编程的三大特性:深入解析继承机制(一)
【C++】面向对象编程的三大特性:深入解析继承机制
|
1月前
|
存储 编译器 程序员
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(二)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值