C++ std::call_once
std::call_once 的定义与功能
std::call_once 是 C++11 标准引入的一种工具,用于确保某段代码只被执行一次,通常用于实现线程安全的单例模式或初始化操作。它结合了 std::once_flag 使用。
核心特点:
- 线程安全性:多个线程同时调用 std::call_once 时,只有一个线程会执行指定的代码,其余线程会等待该操作完成。
- 效率:只在首次调用时执行初始化代码,后续调用直接返回。
头文件:
需要包含 。
主要成员:
std::once_flag:
是一个辅助对象,用于记录是否已经执行过某段代码。
std::call_once:
负责调用指定的初始化函数,确保只执行一次。
用法
函数签名:
template< class Callable, class... Args >
void std::call_once( std::once_flag& flag, Callable&& func, Args&&... args );
- flag:std::once_flag 对象,用于标记代码是否已被执行。
- func:可调用对象,表示需要执行的函数。
- args:传递给 func 的参数。
参考代码
以下代码演示如何使用 std::call_once 确保某段代码在多线程环境下只被执行一次:
#include <iostream>
#include <mutex>
#include <thread>// 声明一个 std::once_flag 对象
std::once_flag initFlag;// 定义需要执行的初始化函数
void initialize() {std::cout << "Initialization code executed by thread: " << std::this_thread::get_id() << std::endl;
}// 每个线程都调用这个函数
void threadFunction() {std::cout << "Thread " << std::this_thread::get_id() << " attempting to initialize..." << std::endl;// 确保初始化代码只执行一次std::call_once(initFlag, initialize);std::cout << "Thread " << std::this_thread::get_id() << " finished execution." << std::endl;
}int main() {// 启动多个线程std::thread t1(threadFunction);std::thread t2(threadFunction);std::thread t3(threadFunction);// 等待线程完成t1.join();t2.join();t3.join();return 0;
}
参考代码输出结果
Thread 140701600769792 attempting to initialize...
Initialization code executed by thread: 140701600769792
Thread 140701600769792 finished execution.
Thread 140701592377088 attempting to initialize...
Thread 140701592377088 finished execution.
Thread 140701583984384 attempting to initialize...
Thread 140701583984384 finished execution.
Thread 140266100016896 attempting to initialize...
Initialization code executed by thread: 140266100016896
Thread 140266100016896 finished execution.
Thread 140266083231488 attempting to initialize...
Thread 140266083231488 finished execution.
Thread 140266091624192 attempting to initialize...
Thread 140266091624192 finished execution.
Thread Thread 139840844814080 attempting to initialize...
Thread 139840853206784 attempting to initialize...
139840861599488 attempting to initialize...
Initialization code executed by thread: 139840861599488
Thread 139840861599488 finished execution.
Thread 139840844814080 finished execution.
Thread 139840853206784 finished execution.
注意事项
1. std::once_flag 是不可复制的:
必须以引用形式传递。
每个要初始化的独立任务都需要单独的 std::once_flag 对象。
2. std::call_once 的线程安全性:
使用低级同步原语(如原子操作)实现,性能较好。
3. 典型用例:
实现单例模式的线程安全初始化。
确保昂贵的初始化代码只运行一次。