C++11新特性之线程std::call_once

C++ std::call_once

std::call_once 的定义与功能

std::call_once 是 C++11 标准引入的一种工具,用于确保某段代码只被执行一次,通常用于实现线程安全的单例模式或初始化操作。它结合了 std::once_flag 使用。

核心特点:

  1. 线程安全性:多个线程同时调用 std::call_once 时,只有一个线程会执行指定的代码,其余线程会等待该操作完成。
  2. 效率:只在首次调用时执行初始化代码,后续调用直接返回。

头文件:

需要包含 。

主要成员:

std::once_flag:
是一个辅助对象,用于记录是否已经执行过某段代码。
std::call_once:
负责调用指定的初始化函数,确保只执行一次。

用法

函数签名

template< class Callable, class... Args >
void std::call_once( std::once_flag& flag, Callable&& func, Args&&... args );
  1. flag:std::once_flag 对象,用于标记代码是否已被执行。
  2. func:可调用对象,表示需要执行的函数。
  3. 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. 典型用例:
实现单例模式的线程安全初始化。
确保昂贵的初始化代码只运行一次。

### 使用 `std::call_once` 创建单例模式 为了确保线程安全并仅初始化一次对象,可以利用 C++11 中引入的 `std::call_once` 函数配合 `std::once_flag` 来实现单例模式。这种方式能够有效防止多线程环境下多次实例化问题的发生。 下面是一个基于上述方法构建的 Singleton 类模板示例: ```cpp #include <iostream> #include <mutex> template<typename T> class Singleton { private: static T* instance; static std::once_flag initFlag; protected: // 构造函数设为保护类型以阻止外部直接创建对象 Singleton() {} public: ~Singleton() {} // 获取唯一实例的方法 static T& GetInstance() { std::call_once(initFlag, [](){ instance = new T(); }); return *instance; } // 删除拷贝构造函数和赋值操作符来保证单一性 Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; }; // 静态成员变量定义与初始化 template<typename T> T* Singleton<T>::instance = nullptr; template<typename T> std::once_flag Singleton<T>::initFlag; int main() { auto& obj = Singleton<MyClass>::GetInstance(); // 进一步的操作... } ``` 此代码片段展示了如何通过静态局部变量以及 lambda 表达式的组合方式,在首次调用 `GetInstance()` 方法时完成类实例的一次性初始化过程[^1]。 同时也删除了复制控制成员(即拷贝构造函数和赋值运算符),从而确保该类不会被意外地重复实例化[^2]。 值得注意的是,这种方法依赖于 C++11 或更新的标准支持;因此对于某些旧版编译器可能无法正常工作[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值