通知图标

欢迎访问津桥芝士站

C++20 : std::atomic::wait 和 std::atomic::notify_one/notify_all

来自AI助手的总结
C++20引入了`std::atomic<T>::wait`、`notify_one`和`notify_all`,增强了多线程同步的效率与灵活性。

引入

在 C++20 中,引入了用于原子变量的 std::atomic<T>::wait 和 std::atomic<T>::notify_onestd::atomic<T>::notify_all。这些功能使得 C++ 对于线程同步的支持更加丰富、灵活。在多线程编程中,线程之间的通信和协作尤为重要,使用原子变量和条件等待可以减少对轮询的依赖,提升系统的效率和响应能力。

std::atomic<T>::wait 提供了一个条件等待机制,允许线程在某个条件满足之前进入等待状态。相应的,notify_one 和 notify_all 方法则用于唤醒等待中的线程。这一特性特别适用于需要高效阻塞和同步的场景,例如生产者-消费者模式、线程池等。

1. std::atomic<T>::wait 和 std::atomic<T>::notify_one/notify_all 的基本特性

1.1 函数定义

  • wait:

    void wait(T expected);

    此函数使调用线程阻塞,直到原子变量的值不等于 expected

  • notify_one:

    void notify_one();

    此函数用于唤醒等待在同一原子变量上的某个线程。

  • notify_all:

    void notify_all();

    此函数用于唤醒所有等待在同一原子变量上线程。

1.2 适用场景

这些功能在需要线程间高效通知和等待的场景中尤为有效,能避免不必要的 CPU 轮询。同时,使用原子变量使得数据访问和变动变得安全和简单。

2. 函数语法介绍

在使用这些新特性时,语法可以这样表示:

#include <atomic>

std::atomic<int> atomicVar;

// 等待
atomicVar.wait(expected_value);

// 唤醒一个等待的线程
atomicVar.notify_one();

// 唤醒所有等待的线程
atomicVar.notify_all();

3. 完整示例代码

下面的示例展示了如何使用 std::atomic<T>::wait 和相应的通知方法进行线程同步:

#include <iostream>
#include <thread>
#include <atomic>
#include <chrono>

std::atomic<int> flag(0); // 原子变量用于控制

void waitingThread() {
    std::cout << "Thread is waiting for the flag to change..." << std::endl;
    flag.wait(0); // 等待flag不等于0
    std::cout << "Flag has changed! Thread is waking up." << std::endl;
}

void signalingThread() {
    std::this_thread::sleep_for(std::chrono::seconds(2)); // 短暂延迟
    flag.store(1); // 改变flag的值
    std::cout << "Flag changed to 1. Notifying the waiting thread." << std::endl;
    flag.notify_one(); // 唤醒一个等待的线程
}

int main() {
    std::thread t1(waitingThread); // 创建等待线程
    std::thread t2(signalingThread); // 创建信号线程

    t1.join();
    t2.join();

    return 0;
}

4. 代码解析

  1. 原子变量 flag

    • std::atomic<int> flag(0); 定义了一个原子整型变量 flag,初始值为 0。这一变量用于线程之间的信号传递。
  2. 等待线程 waitingThread

    • 该线程调用 flag.wait(0),进入等待状态,直至 flag 的值不再为 0。
  3. 信号线程 signalingThread

    • 该线程首先休眠 2 秒,随后将 flag 的值设为 1,并调用 flag.notify_one() 唤醒一个等待线程。
  4. 主线程

    • 在 main() 函数中,启动这两个线程并等待它们结束。

5. 适用场景分析

5.1 生产者-消费者模式

在生产者-消费者模型中,生产者可以在缓冲区已满时使消费者等待,直到允许消费后再通知。

5.2 线程池和任务管理

在多线程任务调度时,可以使用原子变量来指示某个任务的完成或准备状态,通过 wait 和 notify 方法合理控制任务的执行顺序。

5.3 性能优化

相比于传统的条件变量和锁使用方法,std::atomic 提供的原子操作可以减少不必要的上下文切换和轮询,大幅提升程序性能。

6. 总结

C++20 中的 std::atomic<T>::wait 和 notify_one/notify_all 为多线程编程提供了简单而高效的同步机制。借助这些新特性,开发者可以更便捷地实现线程之间的高效协调,避免传统方法中的复杂性和性能损失。

通过运用这些功能,程序不仅可以提高可读性与可维护性,还能提高线程间的通信效率。无论在并发任务的调度、线程模型的实现还是他谓数据共享的场合,这些新引入的功能都将大有裨益。掌握并合理使用 C++20 的新特性,将对高质量、高性能的多线程程序设计产生积极影响。

请登录后发表评论

    没有回复内容