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

在C++多线程编程中,有时需要确保某段代码在整个程序生命周期中只执行一次,比如初始化全局资源、单例对象的构造等。std::call_once 就是为此设计的线程安全机制,它能保证即使多个线程同时尝试调用,目标函数也只会被成功执行一次。
std::call_once 的基本用途
std::call_once 通常与 std::once_flag 配合使用。once_flag 是一个标记,用来记录函数是否已经被调用过。call_once 接收这个标记和一个可调用对象(如函数、lambda),只有当该标记未被设置时,才会执行传入的函数,并自动设置标记防止重复执行。
典型应用场景包括:
单例模式中的延迟初始化 全局配置或日志系统的首次设置 动态加载共享资源(如数据库连接池)
如何使用 std::call_once
使用步骤非常简单:
立即学习“C++免费学习笔记(深入)”;
1. 定义一个全局或静态的 std::once_flag 对象。
2. 在多个线程中调用 std::call_once,传入同一个 once_flag 和初始化函数。
3. 系统自动保证函数仅执行一次。
示例代码:
#include #include #include 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 lock(mtx); if (!initialized) { do_init(); initialized = true; }}
这种方式容易出错,比如忘记双重检查、死锁或内存可见性问题。而 std::call_once 内部已处理所有这些问题,语义清晰且绝对安全。
基本上就这些。std::call_once 提供了一种简洁、高效、线程安全的单次执行机制,特别适合用于初始化场景,避免竞态条件,推荐在多线程环境中优先使用。
以上就是c++++中的std::call_once有什么用_线程安全的单次初始化机制讲解的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1483232.html
微信扫一扫
支付宝扫一扫