英国男女做那个视频网站免费视频网站推荐
std::call_once 是 C++11 标准库中提供的一个线程安全的一次性调用机制,位于 <mutex> 头文件中。它用于确保在多线程环境中,某个函数(或可调用对象)仅被调用一次,无论有多少线程尝试调用它。这种机制常用于实现线程安全的单例模式、延迟初始化等场景。
核心机制
- 依赖 
std::once_flag:
需要与std::once_flag配合使用,once_flag用于标记某个操作是否已被执行。 - 线程安全:
多个线程调用std::call_once时,最终只有一个线程会实际执行目标函数,其他线程会被阻塞,直到目标函数执行完毕。 
基本语法
#include <mutex>std::once_flag flag;  // 必须全局或共享void initialize() {// 仅执行一次的初始化逻辑
}void thread_func() {std::call_once(flag, initialize); // 保证 initialize() 只执行一次
}
 
典型应用场景
1. 线程安全的单例模式
class Singleton {
public:static Singleton& getInstance() {std::call_once(init_flag, []() {instance.reset(new Singleton());});return *instance;}// 禁止拷贝和赋值Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;private:Singleton() = default;  // 私有构造函数~Singleton() = default;static std::unique_ptr<Singleton> instance;static std::once_flag init_flag;
};// 静态成员初始化
std::unique_ptr<Singleton> Singleton::instance;
std::once_flag Singleton::init_flag;
 
2. 延迟初始化
class Resource {
public:void load() { /* 耗时的初始化操作 */ }
};Resource* global_resource = nullptr;
std::once_flag resource_flag;void initResource() {global_resource = new Resource();global_resource->load();
}void useResource() {std::call_once(resource_flag, initResource); // 按需初始化// 使用 global_resource...
}
 
关键特性
- 线程安全:
std::call_once内部通过锁或原子操作保证线程安全,无需手动管理互斥量。 - 异常处理: 
- 如果被调用的函数抛出异常,该异常会传播到调用线程,且 
once_flag不会被标记为“已执行”,其他线程可能会再次尝试执行。 - 若需确保函数仅执行一次(即使抛出异常),需在函数内部处理异常。
 
 - 如果被调用的函数抛出异常,该异常会传播到调用线程,且 
 - 性能优化: 
- 仅第一次调用需要同步,后续调用无锁,性能接近直接访问。
 - 比双重检查锁定(Double-Checked Locking)更简洁安全。
 
 
注意事项
once_flag的生命周期:
std::once_flag必须与目标函数的调用周期一致,通常声明为static或全局变量。- 不可复用:
一个once_flag只能用于一次初始化操作。不同初始化逻辑需使用不同的once_flag。 - C++11 后的单例简化写法:
对于单例模式,C++11 起局部静态变量的初始化是线程安全的,因此可以更简洁地实现:
但Singleton& Singleton::getInstance() {static Singleton instance; // C++11 保证线程安全return instance; }std::call_once在需要动态初始化或复杂逻辑时仍然有用。 
与双重检查锁定的对比
传统双重检查锁定(DCLP):
Singleton* Singleton::instance = nullptr;
std::mutex mtx;Singleton* Singleton::getInstance() {if (instance == nullptr) {              // 第一次检查std::lock_guard<std::mutex> lock(mtx);if (instance == nullptr) {          // 第二次检查instance = new Singleton();}}return instance;
}
 
- 缺点:需手动管理锁,且在某些内存模型下可能出现未定义行为(如指令重排序)。
 - 优势:
std::call_once更简洁且无隐患。 
总结
- 适用场景:单例模式、全局配置加载、资源按需初始化等。
 - 核心价值:简化多线程环境下的“一次性操作”实现,避免手动管理锁和竞态条件。
 - 性能:接近无锁操作,适合高频调用场景。
 
