这些都是笔者辛苦总结,若是对你有用,就点赞收藏支持一下笔者,也是对笔者所写的肯定,谢谢大家!
目录
在CPU缓存架构,CAS只保证比较和交换这个操作是原子的,不保证值的可见性,每个CPU都有自己的缓存,CAS成功后值只更新到当前CPU的缓存中。
之前已经介绍过总线锁定机制和缓存锁定机制了,这次再更加详细地介绍一遍,也可以看看笔者的前篇CAS操作的底层原理(总线锁定机制和缓存锁定机制 )-CSDN博客
总线锁定机制
CPU1 执行CAS操作:
1. 发出LOCK#信号到总线
2. 锁定总线
3. 执行内存读取
4. 比较并交换
5. 写回内存
6. 释放总线锁
总线锁会直接锁住内存访问,其他CPU无法通过总线访问内存,保证了操作的原子性。
缓存锁定机制(MESI协议)
步骤1:CPU1要执行CAS
->检查数据是否在自己的缓存中
->如果是,检查缓存行状态
步骤2:如果缓存行状态是S(共享)
->发出"独占请求"到总线
->其他CPU收到请求后将其缓存行置为I(无效)
->CPU1将缓存行状态改为E(独占)
步骤3:执行CAS操作
->在缓存中完成比较和交换
->将缓存行状态改为M(修改)
步骤4:操作完成后
->其他CPU要访问该数据时发现缓存行无效
->从拥有M状态的CPU缓存中获取最新数据
伪代码展示
class CacheLineOperation {
// 缓存行状态
enum State { MODIFIED, EXCLUSIVE, SHARED, INVALID }
class CacheLine {
State state;
int value;
boolean locked;
}
// CPU缓存操作模拟
void performCAS(CacheLine line, int expect, int update) {
// 1. 获取缓存行独占权
acquireExclusive(line);
// 2. 执行CAS
if (line.value == expect) {
line.value = update;
line.state = State.MODIFIED;
}
// 3. 通知其他CPU
notifyOtherCPUs();
}
}
缓存一致性维护
CPU1 Cache [A=1, M] ──┐
CPU2 Cache [A=1, S] ──┼── 总线
CPU3 Cache [A=1, S] ──┘
当CPU1执行CAS:
1. CPU1发出独占请求
2. CPU2和CPU3将各自的缓存行置为I
3. CPU1执行CAS操作
4. CPU1缓存行状态变为M
两种机制的协同工作
CAS操作执行时如果数据在缓存中:
1. 使用缓存锁
2. MESI协议保证一致性
3. 最终写回内存
CAS操作执行时如果数据不在缓存中:
1. 使用总线锁
2. 直接操作内存
3. 更新所有CPU缓存
写回策略
1. 缓存行被替换
2. 其他CPU请求该数据
3. 显式的内存屏障指令
4. 系统总线请求
示例
public class Counter {
// 错误示例:只用CAS
private int count;
public void increment() {
while (!compareAndSet(count, count + 1)) {}
// 其他线程可能看不到更新
}
// 正确示例:CAS + volatile
private volatile int countWithVolatile;
public void incrementRight() {
while (!compareAndSet(countWithVolatile, countWithVolatile + 1)) {}
// 其他线程立即可见
}
}
这些都是笔者辛苦总结,若是对你有用,就点赞收藏支持一下笔者,也是对笔者所写的肯定,谢谢大家!
标签:缓存,CAS,总线,可见,CPU1,内存,CPU,底层 From: https://blog.csdn.net/xweiran/article/details/145035802