基于CMPXCHG原子指令的最简临界区实现算法问询
用CMPXCHG原子指令实现临界区的最简可行算法
嘿,咱们先把CMPXCHG的工作原理捋明白,再聊临界区的实现——毕竟得先摸透工具的脾气才能用好它嘛。
首先,CMPXCHG的核心逻辑可以用这段伪代码表示,它是个原子操作(整个执行过程不会被其他线程打断):
CMPXCHG (common, old, new): int temp temp <- common if common == old then common <- new return temp
简单说就是:先把共享变量common的值存到临时变量temp里,然后比较common和传入的old值,如果相等,就把common改成new,最后返回一开始存的temp。
最简临界区算法:自旋锁实现
有了这个原子指令,实现临界区的最简方式就是做个自旋锁,核心思路是用一个共享标志位来标记临界区是否被占用,线程通过CMPXCHG原子地尝试获取这个标志,成功就进入临界区,失败就循环等待。
具体实现步骤:
- 定义一个共享的锁标志变量,初始值设为
0(0代表临界区未被锁定,1代表已被锁定):
int lock_flag = 0;
- 线程进入临界区的逻辑:
// 自旋等待,直到成功获取锁 while (CMPXCHG(lock_flag, 0, 1) != 0) { // 空循环,啥也不干,就等锁释放 } // 👇 这里就是你的临界区代码,同一时间只有一个线程能跑到这儿 // ... 执行需要互斥的操作,比如修改共享变量、访问共享资源 ... // 退出临界区,释放锁 lock_flag = 0;
为啥这个算法可行?
- 互斥性:因为CMPXCHG是原子操作,多个线程同时尝试把
lock_flag从0改成1时,只有一个线程能成功(返回值是0,表示之前的lock_flag确实是0,并且已经改成1了),其他线程会拿到返回值1,继续循环等待,直到锁被释放。 - 最简性:没有多余的复杂逻辑,完全靠CMPXCHG的原子性保证互斥,释放锁直接赋值
0就行(毕竟只有持有锁的线程能执行到释放步骤,不会有竞争问题)。
当然,这个最简版本的自旋锁也有局限,比如线程如果在临界区崩溃会导致锁永远无法释放,但题目要的是最简可行的算法,这个完全满足要求。
内容的提问来源于stack exchange,提问作者Vasile
相关产品推荐
相关产品推荐

