std::call_once 与 std::once_flag 配合可确保函数在多线程环境下仅执行一次,常用于单例初始化、全局配置等场景。通过示例可见,三个线程调用 std::call_once 时,do_init 函数只执行一次,避免了手动加锁带来的竞态、死锁等问题,语义清晰且线程安全。

在C++多线程编程中,有时需要确保某段代码在整个程序生命周期中只执行一次,比如初始化全局资源、单例对象的构造等。std::call_once 就是为此设计的线程安全机制,它能保证即使多个线程同时尝试调用,目标函数也只会被成功执行一次。
std::call_once 通常与 std::once_flag 配合使用。once_flag 是一个标记,用来记录函数是否已经被调用过。call_once 接收这个标记和一个可调用对象(如函数、lambda),只有当该标记未被设置时,才会执行传入的函数,并自动设置标记防止重复执行。
典型应用场景包括:
使用步骤非常简单:
立即学习“C++免费学习笔记(深入)”;
1. 定义一个全局或静态的 std::once_flag 对象。示例代码:
#include <iostream>
#include <thread>
#include <mutex>
std::once_flag flag;
void do_init() {
std::cout << "Initialization executed by current thread.\n";
}
void thread_func() {
std::call_once(flag, do_init);
}
int main() {
std::thread t1(thread_func);
std::thread t2(thread_func);
std::thread t3(thread_func);
t1.join();
t2.join();
t3.join();
return 0;
}
尽管三个线程都调用了 std::call_once,但 do_init() 只会被执行一次,输出也只会出现一次。这是由底层互斥锁和状态检测保障的,无需程序员手动加锁判断。
如果不使用 std::call_once,常见的做法是结合互斥量和布尔标志来控制初始化:
std::mutex mtx;
bool initialized = false;
if (!initialized) {
std::lock_guard<std::mutex> lock(mtx);
if (!initialized) {
do_init();
initialized = true;
}
}
这种方式容易出错,比如忘记双重检查、死锁或内存可见性问题。而 std::call_once 内部已处理所有这些问题,语义清晰且绝对安全。
基本上就这些。std::call_once 提供了一种简洁、高效、线程安全的单次执行机制,特别适合用于初始化场景,避免竞态条件,推荐在多线程环境中优先使用。
以上就是c++++中的std::call_once有什么用_线程安全的单次初始化机制讲解的详细内容,更多请关注php中文网其它相关文章!
c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号