在C++的并发编程中,当多个线程需要访问共享资源时,我们需要可靠的同步机制来避免数据竞争。std::atomic::compare_exchange_strong是标准库提供的原子比较交换操作,能够在不使用重量级互斥锁的场景下实现轻量级的并发控制,很多场景下可以用来实现自旋锁这类简单的并发锁结构。

compare_exchange_strong 基本工作原理
compare_exchange_strong属于原子类型的成员函数,它的核心逻辑是:先比较原子变量的当前值是否和预期值相等,如果相等就把原子变量的值替换为新值,返回true;如果不相等就什么都不做,返回false,同时会把原子变量的当前值更新到预期值参数中。
这个操作是原子的,不会被其他线程打断,因此可以保证多线程环境下的操作安全性。和compare_exchange_weak不同的是,compare_exchange_strong不会出现伪失败的情况,也就是只要原子值确实等于预期值,就一定会替换成功,不需要在循环里反复调用。
用 compare_exchange_strong 实现自旋锁实战
自旋锁是一种简单的并发锁,线程在获取锁失败时会不断循环尝试获取,适合锁持有时间短的场景。我们可以用std::atomic<bool>配合compare_exchange_strong来实现一个基础的自旋锁。
自旋锁实现代码
首先定义自旋锁的类结构:
#include <atomic>
class SpinLock {
private:
// 原子变量表示锁状态,false表示未锁定,true表示已锁定
std::atomic<bool> locked{false};
public:
// 获取锁
void lock() {
bool expected = false;
// 循环尝试:当locked为false时,替换为true,获取锁成功
while (!locked.compare_exchange_strong(expected, true)) {
// 如果失败,说明锁已经被其他线程持有,重置expected为false继续尝试
expected = false;
}
}
// 释放锁
void unlock() {
// 直接把锁状态设为false,不需要原子操作也可以,不过这里用store更规范
locked.store(false, std::memory_order_release);
}
};
自旋锁使用示例
接下来用这个自旋锁来保护一个共享计数器,模拟多线程累加的场景:
#include <iostream>
#include <thread>
#include <vector>
// 共享计数器
int counter = 0;
// 实例化自旋锁
SpinLock spinLock;
// 线程执行的函数,对counter累加1000次
void increment() {
for (int i = 0; i < 1000; i++) {
spinLock.lock();
counter++;
spinLock.unlock();
}
}
int main() {
std::vector<std::thread> threads;
// 创建5个线程
for (int i = 0; i < 5; i++) {
threads.emplace_back(increment);
}
// 等待所有线程执行完成
for (auto& t : threads) {
t.join();
}
// 输出最终结果,预期是5000
std::cout << "最终计数器值: " << counter << std::endl;
return 0;
}
使用注意事项
- 内存序选择:上面的示例中lock函数里compare_exchange_strong使用了默认的内存序,实际场景中可以根据需要指定更宽松的内存序来提升性能,比如获取锁时用std::memory_order_acquire,释放锁时用std::memory_order_release。
- 避免死锁:自旋锁不适合在持有锁的线程中调用会阻塞的操作,否则会导致其他线程一直空转浪费CPU资源。如果锁持有时间较长,建议使用std::mutex这类重量级锁。
- 预期值重置:在循环调用compare_exchange_strong时,每次失败后需要把预期值重置为未锁定的状态,否则下一次比较会使用和当前原子值相等的值,导致一直无法进入替换逻辑。
和 compare_exchange_weak 的选择
如果是在循环中使用比较交换操作,compare_exchange_weak可能会因为伪失败导致需要多循环几次,但整体性能可能更高;如果是单次调用,一定要用compare_exchange_strong,避免伪失败导致逻辑错误。在自旋锁的场景下,因为本身就在循环里调用,也可以用compare_exchange_weak,不过需要保证循环逻辑正确。
需要注意的是,compare_exchange_strong的原子性是由硬件保证的,不同平台的支持情况可能有差异,使用前需要确认编译器和目标平台对该接口的支持情况。
std::atomiccompare_exchange_strong并发锁C++修改时间:2026-06-23 06:12:28