C++11中的std::call_once函数位于<mutex>头文件中。

在多线程编程中,有时某个任务只需要执行一次,此时可以用C++11中的std::call_once函数配合std::once_flag来实现。如果多个线程需要同时调用某个函数,std::call_once可以保证多个线程对该函数只调用一次。也可用在解决线程安全的单例模式。

template<class Callable, class... Args >
void call_once(std::once_flag& flag, Callable&& f, Args&&... args );

std::call_once: Executes the Callable object f exactly once, even if called from several threads.

Each group of call_once invocations that receives the same std::once_flag object will meet the following requirements:

(1). Exactly one execution of exactly one of the functions (passed as f to the invocations in the group) is performed. It is undefined which function will be selected for execution. The selected function runs in the same thread as the call_once invocation it was passed to.

(2). No invocation in the group returns before the above-mentioned execution of the selected function is completed successfully, that is, doesn't exit via an exception.

(3). If the selected function exits via exception, it is propagated to the caller. Another function is then selected and executed.

下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

#include "call_once.hpp"
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
#include <future>/*
template< class Callable, class... Args >
void call_once( std::once_flag& flag, Callable&& f, Args&&... args );Calls fn passing args as arguments, unless another thread has already executed
(or is currently executing) a call to call_once with the same flag.If another thread is already actively executing a call to call_once with the same flag,
it causes a passive execution: Passive executions do not call fn but do not return until
the active execution itself has returned, and all visible side effects are synchronized at
that point among all concurrent calls to this function with the same flag.If an active call to call_once ends by throwing an exception (which is propagated
to its calling thread) and passive executions exist, one is selected among these
passive executions, and called to be the new active call instead.Note that once an active execution has returned, all current passive executions
and future calls to call_once (with the same flag) also return without becoming active executions.The active execution uses decay copies of the lvalue or rvalue references of fn and args,
ignoring the value returned by fn.
*/namespace call_once_ {
/
// reference: http://en.cppreference.com/w/cpp/thread/call_once
namespace {
std::once_flag flag1, flag2;void simple_do_once()
{std::call_once(flag1, [](){ std::cout << "Simple example: called once\n"; });
}void may_throw_function(bool do_throw)
{if (do_throw) {std::cout << "throw: call_once will retry\n"; // this may appear more than oncethrow std::exception();}std::cout << "Didn't throw, call_once will not attempt again\n"; // guaranteed once
}void do_once(bool do_throw)
{try {std::call_once(flag2, may_throw_function, do_throw);}catch (...) {}
}
}int test_call_once_1()
{std::thread st1(simple_do_once);std::thread st2(simple_do_once);std::thread st3(simple_do_once);std::thread st4(simple_do_once);st1.join();st2.join();st3.join();st4.join();/*std::thread t1(do_once, true);std::thread t2(do_once, true);std::thread t3(do_once, false);std::thread t4(do_once, true);t1.join();t2.join();t3.join();t4.join();*/return 0;
}///
// reference: http://www.cplusplus.com/reference/mutex/call_once/
namespace {
int winner;
void set_winner(int x) { winner = x; }
std::once_flag winner_flag;void wait_1000ms(int id) {// count to 1000, waiting 1ms between increments:for (int i = 0; i<1000; ++i)std::this_thread::sleep_for(std::chrono::milliseconds(1));// claim to be the winner (only the first such call is executed):std::call_once(winner_flag, set_winner, id);
}
}int test_call_once_2()
{std::thread threads[10];// spawn 10 threads:for (int i = 0; i<10; ++i)threads[i] = std::thread(wait_1000ms, i + 1);std::cout << "waiting for the first among 10 threads to count 1000 ms...\n";for (auto& th : threads) th.join();std::cout << "winner thread: " << winner << '\n';return 0;
}// reference: http://www.modernescpp.com/index.php/thread-safe-initialization-of-a-singleton
namespace {
/*constexpr*/const auto tenMill = 10000;class MySingleton{
public:static MySingleton& getInstance(){std::call_once(initInstanceFlag, &MySingleton::initSingleton);// volatile int dummy{};return *instance;}
private:MySingleton() = default;~MySingleton() = default;MySingleton(const MySingleton&) = delete;MySingleton& operator=(const MySingleton&) = delete;static MySingleton* instance;static std::once_flag initInstanceFlag;static void initSingleton(){instance = new MySingleton;}
};MySingleton* MySingleton::instance = nullptr;
std::once_flag MySingleton::initInstanceFlag;std::chrono::duration<double> getTime(){auto begin = std::chrono::system_clock::now();for (size_t i = 0; i <= tenMill; ++i){MySingleton::getInstance();}return std::chrono::system_clock::now() - begin;};
}int test_call_once_3()
{auto fut1 = std::async(std::launch::async, getTime);auto fut2 = std::async(std::launch::async, getTime);auto fut3 = std::async(std::launch::async, getTime);auto fut4 = std::async(std::launch::async, getTime);auto total = fut1.get() + fut2.get() + fut3.get() + fut4.get();std::cout << total.count() << std::endl;return 0;
}} // namespace call_once_

GitHub: https://github.com/fengbingchun/Messy_Test

C++11多线程中std::call_once的使用相关推荐

  1. Multi-thread--C++11多线程中std::call_once的使用

    C++11中的std::call_once函数位于<mutex>头文件中. 在多线程编程中,有时某个任务只需要执行一次,此时可以用C++11中的std::call_once函数配合std: ...

  2. C++11 多线程(std::thread)详解

    注:此教程以 Visual Studio 2019 Version 16.10.3 (MSVC 19.29.30038.1) 为标准,大多数内容参照cplusplus.com里的解释 此文章允许转载, ...

  3. C++11多线程之 std::packaged_task

    简介 先给出官网的一个地址:http://www.cplusplus.com/reference/future/packaged_task/?kw=packaged_task 个人认为,相当于一个装饰 ...

  4. 【多线程】C++11进行多线程开发 (std::thread)

    文章目录 创建线程 std::thread 类 使用join() 使用 detach() 警惕作用域 线程不能复制 给线程传参 传递指针 传递引用 以类成员函数为线程函数 以容器存放线程对象 互斥量 ...

  5. C++11中std::condition_variable的使用

    <condition_variable>是C++标准程序库中的一个头文件,定义了C++11标准中的一些用于并发编程时表示条件变量的类与方法等. 条件变量是并发程序设计中的一种控制结构.多个 ...

  6. Multi-thread--C++11中std::condition_variable的使用

    <condition_variable>是C++标准程序库中的一个头文件,定义了C++11标准中的一些用于并发编程时表示条件变量的类与方法等. 条件变量是并发程序设计中的一种控制结构.多个 ...

  7. C++11多线程 内存序(std::memory_order_consume)

    引言 在C++多线程 内存序系列文章中,已经介绍了如下三种内存序 C++11多线程 内存序(std::memory_order_seq_cst ) C++11多线程 内存序(std::memory_o ...

  8. C++11中std::forward_list单向链表的使用

    std::forward_list是在C++11中引入的单向链表或叫正向列表.forward_list具有插入.删除表项速度快.消耗内存空间少的特点,但只能向前遍历.与其它序列容器(array.vec ...

  9. C++/C++11中std::string用法汇总

    C++/C++11中std::string是个模板类,它是一个标准库.使用string类型必须首先包含<string>头文件.作为标准库的一部分,string定义在命名空间std中. st ...

最新文章

  1. Electron 调用系统工具记事本、计算器等
  2. keras module 'tensorflow' has no attribute 'placeholder'
  3. Mysql中常用的函数汇总
  4. 深度学习-超参数和交叉验证
  5. C# 海康DVR客户端开发系列(2)—— 封装API (1)
  6. 计算机工程师英语简历模板,计算机软件工程师英文简历模板
  7. qlabel显示两行_PyQt5 系统化学习: QLabel
  8. JN5169 NXP ZigBee PRO 无线网络应用所需的常见操作(一)
  9. idea clean Process terminated
  10. MySQL 从删库到跑路
  11. 连接阿里云RDS数据库报错
  12. 树莓派 4b 配置 USB 网络连接
  13. 集装箱编号校验码规则及java程序的实现
  14. scala sortBy and sortWith
  15. python全套教程百度云-老男孩python全套视频教程百度云资源下载
  16. XGBoost线性回归工控数据分析实践案例(原生篇)
  17. 杰奇1.7用php53,杰奇CMS 1.7商业版注入漏洞
  18. c语言 计算分段函数
  19. CNZZ 统计代码及作弊分析
  20. 解密中企动力:80余家公司近万人个个都干营销 不骗你

热门文章

  1. logback-spring.xml读取spring的属性
  2. PCL:点云中的超体素数据
  3. 大意!6行代码,“报废”5片单片机!
  4. c++中static_cast用法与uchar/char的区别
  5. tf2运行YOLOv4(tflite)
  6. 应用YOLOV4 - DeepSort 实现目标跟踪
  7. Linux那些事儿之我是Sysfs(11)sysfs 创建普通文件
  8. Linux那些事儿之我是Sysfs(7)dentry与inode
  9. 【YOLOV4】(7) 特征提取网络代码复现(CSPDarknet53+SPP+PANet+Head),附Tensorflow完整代码
  10. 高亮提示、聚焦控件并滚动到浏览器中干好可以查看到该控件的位置