1.什么是 CAS?
CAS操作——Compare & Set,或是 Compare & Swap,现在几乎所有的CPU指令都支持CAS的原子操作,X86下对应的是 CMPXCHG 汇编指令。有了这个原子操作,我们就可以用其来实现各种无锁(lock free)的数据结构。
int compare_and_swap (int* reg, int oldval, int newval)
{
int old_reg_val = *reg;
if (old_reg_val == oldval)
{ *reg = newval; }
return old_reg_val;
}
// test
bool compare_and_swap (int *addr, int oldval, int newval)
{ if ( *addr != oldval )
{ return false; } *addr = newval;
return true; }
- Fetch And Add,一般用来对变量做 +1 的原子操作
- Test-and-set,写值到某个内存位置并传回其旧值。汇编指令BST
- Test and Test-and-set,用来低低Test-and-Set的资源争夺情况
2.在实际的C/C++程序中,CAS的各种实现版本如下
3) C++11中的CAS
C++11中的STL中的atomic类的函数可以让你跨平台
template< class T >
bool atomic_compare_exchange_weak( std::atomic* obj,T* expected, T desired );
template< class T >
bool atomic_compare_exchange_weak( volatile std::atomic* obj,T* expected, T desired );
3.CAS需要硬件支持吗?
必须有硬件支持,原子性本质:CAS 需要 单指令或硬件监控机制 保证操作的不可分割性,
软件无法直接模拟,若无硬件支持,无法在多核/多线程环境下保证原子性(例如,软件模拟的“CAS”可能被中断或并发修改破坏)。
4.不同 CPU 架构通过 专用指令 实现 CAS 的原子性
架构 | 指令 | 机制 |
---|---|---|
x86/x64 | LOCK CMPXCHG | 通过 LOCK 前缀强制总线锁定,保证多核原子性。 |
ARM | LDREX + STREX | 基于 独占访问标记(Exclusive Monitor),由硬件监控内存访问的原子性。 |
我们可以通过工具 Compiler Explorer 进行验证。目前只是验证X86平台上的指令。
#include <atomic>
#include <iostream>void test_atomic_ops(std::atomic<bool>& flag) {// 1. load() 操作bool val1 = flag.load(std::memory_order_relaxed);// 2. store() 操作flag.store(true, std::memory_order_relaxed);// 3. exchange() 操作bool old_val = flag.exchange(false, std::memory_order_relaxed);// 4. compare_exchange_weak() 操作bool expected = false;flag.compare_exchange_weak(expected, true, std::memory_order_relaxed);
}int main() {std::atomic<bool> flag{false};test_atomic_ops(flag);return 0;
}
从上面可以看到,一些基本的操作,如果本身就是一条汇编指令的,那么自然就是cas,
比方说是.load,store.方法,
compare_exchage_weak()用到了lock cmpxchg BYTE PTR [rdi], dl,
暂时编辑到这里,会在最近更新...