引入
在 C++20 中,引入了用于原子变量的 std::atomic<T>::wait
和 std::atomic<T>::notify_one
,std::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. 代码解析
-
原子变量
flag
:std::atomic<int> flag(0);
定义了一个原子整型变量flag
,初始值为 0。这一变量用于线程之间的信号传递。
-
等待线程
waitingThread
:- 该线程调用
flag.wait(0)
,进入等待状态,直至flag
的值不再为 0。
- 该线程调用
-
信号线程
signalingThread
:- 该线程首先休眠 2 秒,随后将
flag
的值设为 1,并调用flag.notify_one()
唤醒一个等待线程。
- 该线程首先休眠 2 秒,随后将
-
主线程:
- 在
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 的新特性,将对高质量、高性能的多线程程序设计产生积极影响。
没有回复内容