马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
目次
处置惩罚器级别的实现
总线锁定机制
缓存锁定机制
MSEI表现缓存行的四种状态
MESI协议状态转换
CAS利用是不包管可见性的
CAS根本概念
ABA标题的处置惩罚
性能思量
先总结一下,CAS(Compare And Swap)是一种原子利用,它比力当前内存值与渴望值,如果相当则更新为新值,CAS是一种硬件级的原子利用,通过总线锁或缓存锁实现原子性,在使用缓存锁的时间缓存同等性协议包管数据同等性。
而Java通过native方法调用底层CAS指令,须要思量ABA标题和性能优化,而cas这种机制包管了在多处置惩罚器体系中的原子利用,是实现无锁并发的底子。
处置惩罚器级别的实现
x86汇编中的CMPXCHG指令示例
lock cmpxchg [内存地点], 新值
处置惩罚器通过特别的指令(如x86的CMPXCHG)来实现CAS利用,并使用LOCK前缀包管利用的原子性。
总线锁定机制
CPU1 ----┐
CPU2 ----├── 总线 -----> 内存
CPU3 ----┘
↑
LOCK信号
当一个CPU发出LOCK信号时,其他CPU无法通过总线访问内存,包管了利用的原子性。但这种方式开销较大。
缓存锁定机制
CPU1 Cache [数据A: M] ─┐
CPU2 Cache [数据A: I] ─┼── 总线 ──> 内存[数据A]
CPU3 Cache [数据A: I] ─┘
使用缓存同等性协议(MESI),通过缓存状态控制来包管原子性,服从更高。
MSEI表现缓存行的四种状态
M(Modify)表现共享数据只缓存在当前 CPU 缓存中, 而且是被修改状态,也就是缓存的数据和主内存中的数据差异等
E(Exclusive)表现缓存的独占状态,数据只缓存在当前 CPU 缓存中,而且没有被修改
S(Shared)表现数据大概被多个 CPU 缓存,而且各个缓存中的数据和主内存数据同等
I(Invalid)表现缓存已经失效
MESI协议状态转换
CPU1实行CAS:
1. 发出监听哀求
2. 等候其他CPU相应
3. 确认无辩论后实行
4. 广播状态变动
CPU在读取一个数据时会先发起监听,去监听其他CPU的对这个数据缓存行的状态。
如果本CPU缓存行状态是I,则须要从内存中读取,并把缓存行状态置为S。
如果本CPU缓存行的状态不是I,则可以直接读取缓存中的值,如果其他CPU也有该数据的缓存且状态是M,则须要等候其把缓存更新到内存后再读取。
CPU更新了缓存行的状态了之后会发广播来更新其他CPU的缓存行状态。
CAS利用是不包管可见性的
这一点要特别留意,CAS的利用是不包管可见性的,可见性是实现CAS利用的条件,如果连可见性都包管不了,这又怎么实现CAS利用?
CAS利用通常与volatile共同使用,通过内存屏蔽包管可见性。
CAS根本概念
- // CAS操作的伪代码
- public boolean compareAndSet(int expectedValue, int newValue) {
- // 原子操作,比较并交换
- // V是要更新的变量,E是期望值,N是新值
- if (V == expectedValue) {
- V = newValue;
- return true;
- }
- return false;
- }
复制代码 CAS(Compare And Swap)是一种原子利用,它比力当前内存值与渴望值,如果相当则更新为新值。
ABA标题的处置惩罚
- public class AtomicStampedReference<V> {
- private static class Pair<T> {
- final T reference;
- final int stamp;
-
- private Pair(T reference, int stamp) {
- this.reference = reference;
- this.stamp = stamp;
- }
- }
- }
复制代码 ABA是CAS利用的经典标题了,可以通过版本号或时间戳办理ABA标题。
性能思量
- // 自旋等待示例
- public void spinLock() {
- while (!cas.compareAndSet(false, true)) {
- // 自旋等待
- Thread.onSpinWait(); // Java 9+
- }
- }
复制代码 CAS失败时通常接纳自旋等候,须要思量自旋次数和退避战略。
|