C++ 并发编程 | std::call_once

本文介绍了C++11中的std::call_once函数,用于确保一个函数在多线程环境下仅执行一次,配合once_flag用于线程安全的单例模式示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

某些场景下,需要代码只被执行一次,比如单例类的初始化,考虑到多线程安全,需要进行加锁控制。C++11中提供的call_once可以很好的满足这种需求,使用又非常简单。

一、std::call_once

1、函数声明

函数定义于头文件<mutex>call_once保证可调用对象_Fx只被执行一次,即使在多线程场景,函数原型:

template<class _Fn, class... _Args> inline
	void (call_once)(once_flag& _Flag, _Fn&& _Fx, _Args&&... _Ax)
  • _Flag:标志对象,用于指示 _Fx 是否已调用过
  • _Fx:可调用对象
  • _Ax:传递的参数

使用call_once注意的事项:

  • 如果在调用 call_once 的时刻,_Flag 指示 _Fx 已经调用过,那么 call_once 会立即返回
  • 如果在调用 _Fx 时抛出了异常,那么异常将传播给 call_once 的调用方,并且 _Flag 不会被翻转
  • 如果调用正常返回,那么 _Flag 被翻转,并保证以同一 _Flagcall_once 的其他调用立即返回
  • 如果有多个线程同时在 _Flag 未翻转时调用 call_once,那么这些调用将被组成单独全序,并被依次执行

2、std::once_flag

用来表示可调用对象是否成功执行过,std::once_flag是不允许修改的,其拷贝构造函数和operator=函数都声明为delete,声明如下:

struct once_flag
	{	// opaque data structure for call_once()
	constexpr once_flag() _NOEXCEPT
		: _Opaque(0)
		{	// default construct
		}

	once_flag(const once_flag&) = delete;
	once_flag& operator=(const once_flag&) = delete;

	void *_Opaque;
	};

注意:还有一个要注意的地方是once_flag的生命周期,它必须要比使用它的线程的生命周期要长。所以通常定义成全局变量比较好。

3、应用示例

使用call_once实现一个单例模式,如下:

static std::once_flag oc;  // 用于call_once的局部静态变量

Singleton* Singleton::m_instance;

Singleton* Singleton::getInstance() {
    std::call_once(oc, [&] () { 
    	m_instance = new Singleton(); 
    });
    
    return m_instance;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值