1. C++20原子变量新特性概览
C++20标准为原子变量引入了三个重要的新成员函数:wait()、notify_one()和notify_all()。这三个函数为原子操作带来了全新的等待/通知机制,让开发者能够以更高效的方式实现线程同步。作为C++并发编程的重要升级,这套机制本质上提供了一种无锁的条件变量功能。
在实际项目中,我们经常遇到这样的场景:某个线程需要等待原子变量达到特定值后才能继续执行。传统做法是使用互斥锁配合条件变量,但这种方案存在锁竞争和上下文切换的开销。C++20的新特性允许我们直接通过原子变量本身实现等待和唤醒,完全避免了锁的使用。
注意:虽然这套新接口使用起来类似于条件变量,但其底层实现通常依赖于操作系统的futex等机制,在性能上具有明显优势。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 函数成员详解与使用场景
2.1 wait()函数的工作原理
wait()函数的签名如下:
cpp复制void wait(T old, memory_order order = memory_order::seq_cst) const noexcept;
这个函数会让当前线程阻塞等待,直到原子变量的值发生变化。其工作流程是:
- 首先检查原子变量的当前值是否与参数old相等
- 如果不等,立即返回(不阻塞)
- 如果相等,则线程进入等待状态
- 当其他线程修改该原子变量并调用notify函数时,等待的线程会被唤醒
- 被唤醒后再次检查原子变量的值,如果仍等于old,则继续等待(防止虚假唤醒)
典型使用场景:
cpp复制std::atomic<int> flag(0);
// 线程1:等待flag变为1
flag.wait(0); // 阻塞直到flag不再是0
// 线程2:修改flag并通知
flag.store(1);
flag.notify_all();
2.2 notify_one()与notify_all()的区别
notify_one()和notify_all()都用于唤醒等待的线程,但唤醒策略不同:
notify_one():唤醒一个正在wait的线程(如果有多个线程在等待,具体唤醒哪个不确定)notify_all():唤醒所有正在wait的线程
选择建议:
- 当只有一个等待线程需要被唤醒时,使用notify_one()更高效
- 当多个等待线程需要同时响应时,使用notify_all()
- 不确定等待线程数量时,保守选择notify_all()
内存序考虑:
cpp复制// 推荐的内存序使用方式
flag.store(1, std::memory_order::release);
flag.notify_one();
// 或者
flag.store(1, std::memory_order::relaxed);
std::atomic_thread_fence(std::memory_order::release);
flag.noti
