CAS
CAS:compar and swap,是一种自旋锁
属于乐观锁,是解决多线程并行情况下使用锁造成性能损耗的一种机制,CAS操作包含三个操作数——内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。无论哪种情况,它都会在CAS指令之前返回该位置的值。CAS有效地说明了“我认为位置V应该包含值A;如果包含该值,则将B放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。
ABA问题
加入有三个线程,线程A读取内存中数据为0,然后i++,线程B读取内存中数据位0,然后i++,线程A运行比较慢,线程B把1写入内存,然后有一个线程C,读取内存中数据位1,进行i–操作,然后把0写入内存,这个时候线程A才运行完毕,然后读取内存中数据位0,认为没有发生修改,则把1写入数据。
这个时候线程A认为内存中0的数据没有修改,写入内存了,但是这个数据确实发生了修改。这就是ABA问题
解决方案:
- 不管
- 这个一个值,我不在在乎,你想改就改,我要的是最终的值
- 添加版本
- 这是一个引用,应用的地址没有发生改变,但是这个地址指向的对象内容可能已经改变了,这个时候添加版本号解决
- 在值上添加一个版本号,(可以是线程id)在比较的时候会比较值和版本号,如果这两个都一样,则会赋值
CAS在java中的底层实现是native,是用的C++实现的(下面为linuxX86操作系统的实现)
Unsafe_CompareAnSwapINT
调用Atomic的cmpxchg
调用汇编码
__asm__
调用cmpxchg1,(如果是多核cpu执行这个方法会添加lock)
最终实现:
lock cmpxchg 指令
在多核cpu情况下,如果没有加锁,执行还不是原子性的,有可能被其他核干扰,所以添加了lock解决,总线嗅探(Bus Snooping)技术。这个策略总线嗅探,本质上就是把所有的读写请求都通过总线(Bus)广播给所有的CPU核心,然后让各个核心去“嗅探”这些请求,再根据本地的情况进行响应。
synchronized和violate的底层实现都是lock cmpxchg 指令
硬件:lock指定在执行后面指令的时候锁定一个北桥信号(不采用锁总线的方式)
推荐文章:
cpu底层cas原理:https://blog.csdn.net/weixin_30691871/article/details/100004896