多线程环境下,无锁实现std::atomic计数器条件自增是否可行?
可以不用锁实现,用原子CAS操作即可
你的需求完全可以通过std::atomic提供的**比较并交换(CAS)**操作来实现,不需要依赖互斥锁。核心思路是利用原子操作的特性,通过循环重试来保证"读取a的值→判断是否小于b→自增a"逻辑的线程安全。
实现代码示例
#include <atomic> // 当a严格小于b时自增a,返回a的旧值;不满足条件时返回-1(可根据需求调整返回逻辑) int increment_a_if_less_than_b(std::atomic<int>& a, std::atomic<int>& b) { int a_old = a.load(std::memory_order_acquire); do { // 检查当前a的值是否小于b if (a_old >= b.load(std::memory_order_acquire)) { return -1; } // 原子尝试将a从a_old更新为a_old+1 // 若CAS失败,a_old会自动被更新为a的最新值,进入下一轮重试 } while (!a.compare_exchange_weak(a_old, a_old + 1, std::memory_order_release, std::memory_order_acquire)); // CAS成功,返回a的旧值 return a_old; }
工作原理
- 原子加载:先用
load原子性读取a的当前值到a_old,保证读取操作不被打断。 - 条件判断:读取b的当前值做比较——因为b只执行自增操作,值只会越来越大,所以一旦
a_old < b成立,后续即使b被其他线程修改,这个条件依然有效(不会出现"刚判断满足,b就变小导致不满足"的情况)。 - CAS重试:调用
compare_exchange_weak原子性完成"比较+更新":- CAS成功:说明从读取
a_old到更新的过程中,a没有被其他线程修改,直接返回旧值。 - CAS失败:说明其他线程已经修改了a的值,此时
a_old会自动被更新为a的最新值,循环重新判断条件并尝试操作。
- CAS成功:说明从读取
为什么不需要锁?
你提到的"比较-自增需要锁保证中间不被修改"是针对普通非原子操作的场景,但std::atomic的CAS操作本身就是原子的——它能保证"比较当前值是否等于预期值,如果是则更新"这一整个过程不会被其他线程打断,完美解决了竞争场景下的原子性需求,且比锁更轻量高效。
内容的提问来源于stack exchange,提问作者g2006
相关产品推荐
相关产品推荐

