通知图标

欢迎访问津桥芝士站

atomic:std::atomic::wait

来自AI助手的总结
C++20引入的std::atomic<T>::wait函数实现了高效的无锁条件等待机制,优化多线程同步,降低资源消耗,提高应用性能。

引入

在 C++20 标准中,<atomic> 头文件被增强,加入了新的功能以支持更复杂的并发场景。其中,std::atomic<T>::wait 函数是一个用来实现无锁条件等待的机制。利用这一功能,线程可以在某个特定的原子变量值没有发生变化时主动挂起自己,从而实现高效的条件同步。这种机制为开发者提供了一种优于传统锁或信号量的方式,降低了对系统资源的消耗,提高了应用程序的性能。

1. 特性与函数介绍

1.1 特性

  • 无锁等待机制:当线程调用 wait 等待时,它将检查指定的原子变量的值。如果该值未改变,线程将被挂起,直到其他线程通知它继续运行。
  • 减少资源占用:与传统的循环检查或主动争用不同,wait 函数有效地减少了 CPU 时间的浪费,提高了系统效率。
  • 安全性wait 函数是在原子操作的上下文中管理的,确保了并发场景中的数据安全性。

1.2 函数语法

std::atomic<T>::wait 的基本用法如下:

#include <atomic>

namespace std {
    template<typename T>
    class atomic {
    public:
        void wait(T expected_value, std::chrono::milliseconds timeout = std::chrono::milliseconds{-1});
    };
}
  • 参数
    • expected_value:线程希望原子变量保持的值。当原子变量值变为其他值时,线程会唤醒。
    • timeout(可选):允许的等待时间。如果为负数,表示等待无限长的时间。

2. 完整示例代码

以下示例展示了如何使用 std::atomic<T>::wait 实现条件等待:

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

std::atomic<int> sharedValue(0);

void waitingThread() {
    std::cout << "Waiting thread waiting for sharedValue to change..." << std::endl;
    sharedValue.wait(0); // 等待 sharedValue 为 0
    std::cout << "Waiting thread awakened! sharedValue is now: " << sharedValue.load() << std::endl;
}

void notifyingThread() {
    std::this_thread::sleep_for(std::chrono::seconds(2)); // 确保 waitingThread 首先挂起
    sharedValue.store(1); // 改变 sharedValue 的值
    std::cout << "Notifying thread changed sharedValue to 1." << std::endl;
}

int main() {
    std::thread waitThread(waitingThread);
    std::thread notifyThread(notifyingThread);

    waitThread.join();
    notifyThread.join();

    std::cout << "Main thread ends." << std::endl;
    return 0;
}

3. 代码解析

  1. 引入头文件

    • 代码开始时包括 <atomic><thread> 和 <chrono> 头文件,以支持原子操作和多线程功能。
  2. 定义原子变量

    • 使用 std::atomic<int> sharedValue(0) 创建一个原子变量,以保证在多线程环境下的安全操作。
  3. 定义线程函数

    • waitingThread 中调用 sharedValue.wait(0),它将挂起,直到 sharedValue 的值不再为 0。
    • notifyingThread 创建一个 2 秒的延迟后,将 sharedValue 的值更改为 1,随后唤醒等待的线程。
  4. 主函数创建线程

    • 在 main 中,首先创建等待线程和通知线程,然后通过 join() 方法等待这两个线程完成。

4. 适用场景分析

4.1 高效的条件变量

std::atomic<T>::wait 特别适用于需要高效条件等待的场景,如生产者-消费者模式,在此环境中,线程可以在等待某个条件时不会占用 CPU 资源。

4.2 减少不断轮询

通过无锁的方式,wait 可以代替传统的条件变量和轮询机制,消耗更少的 CPU 时间,方便处理瞬态变化。

4.3 优化复杂的同步需求

在某些复杂的多线程数据结构中,元素之间可能有非常复杂的依赖关系。使用 wait 描述这些依赖关系时,可以更加自然且高效。

5. 总结

std::atomic<T>::wait 是 C++20 中一个强大而灵活的同步机制,使得线程能以最低的资源占用推迟执行。结合原子操作,利用 wait 函数的无锁等待特性,开发者能够构建出高效的多线程应用程序,有利于在处理并发时减少开销,提高程序的响应能力。掌握和灵活应用这一特性,对于希望提高 C++ 并发程序效率并保持良好性能的开发者来说,具有重要意义。随着开发者更深入地探索无锁编程范式,std::atomic<T>::wait 在未来的多线程应用中必将发挥越来越大的作用。

请登录后发表评论

    没有回复内容

正在唤醒异次元光景……