C++-CAS原理实现自旋锁

转自亿速云

CAS

CAS(Compare and Swap),即比较并替换,实现并发算法时常用到的一种技术,这种操作提供了硬件级别的原子操作(通过锁总线的方式)。CAS操作的原型可以认为是:

1
bool CAS(V, A, B);

其中V代表内存中的变量,A代表期待的值,B表示新值。当V的值与A相等时,将V与B的值交换。

需要强调的是CAS操作是原子的,要么不做,要么全部完成。

C++11利用CAS原理实现自旋锁

首先需要一个 bool 值来表示锁的状态,这里直接使用 atomic

然后需要两个原子操作,CAS 和赋值,C++11 在原子标准库中添加直接提供。

1
2
3
4
5
6
7
8
9
10
11
//CAS
std::atomic::compare_exchange_weak( T& expected, T desired,
std::memory_order order =
std::memory_order_seq_cst );

std::atomic::compare_exchange_strong( T& expected, T desired,
std::memory_order order =
std::memory_order_seq_cst );

//赋值
void store( T desired, std::memory_order order = std::memory_order_seq_cst )

compare_exchange_weak 与 compare_exchange_strong 的区别在于内存中的值与 expected 相等的时候,CAS 操作是否一定能成功,compare_exchange_weak 有概率会返回失败,而compare_exchange_strong 则一定会成功。

因此,compare_exchange_weak 必须与循环搭配使用来保证在失败的时候重试 CAS 操作。

实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <atomic>

class SpinLock
{
public:
SpinLock() : flag_(false)
{}
void lock()
{
bool expect = false;
while (!flag_.compare_exchange_weak(expect, true))
{
//这里一定要将expect复原,执行失败时expect结果是未定的
expect = false;
}
}

void unlock()
{
flag_.store(false);
}

private:
std::atomic<bool> flag_;
};