-
什么是CAS?
-
compareAndSwap,比较交换,是一种无锁原子算法,映射到操作系统就是一条CPU的原子指令
-
执行过程:CAS(V,E,N)
当前实际值、当前期望值、修改后的值 -
多个线程使用CAS操作一个变量时,最多只有一个会成功,其余均会失败
-
失败的线程不会挂起,仅被告知失败,且允许再次尝试(自旋)
-
-
使用无锁的方式完全没有锁竞争带来的线程间频繁调度的开销和阻塞,对死锁问题天生免疫。性能更好
-
底层原理:硬件指令集(原子指令集)
其他原子指令集:-
测试并设置(Tetst-and-Set)
-
获取并增加(Fetch-and-Increment)
-
交换(Swap)
-
比较并交 换(Compare-and-Swap)
-
加载链接/条件存储(Load-Linked/Store-Conditional)
-
-
CPU实现原子指令
-
原子操作是指不可被中断的一个或者一组操作
-
处理器会自动保证基本的内存操作的原子性,也就是一个处理器从内存中读取或者写入一个字节时,其他内存是不能访问这个字节的内存地址。但处理器不能自动保证复杂的内存操作的原子性,比如跨总线宽度、跨多个缓存行或者跨页表的操作
-
总线锁定
和缓存锁定
是处理器保证复杂内存操作原子性的两个机制
-
实现方式
- 总线锁
使用处理器提供的一个LOCK#
信号,当一个处理器在总线上输出此信号时,其他处理器的请求都会被阻塞,此时此处理器可独占共享内存 - 缓存锁
某个CPU对缓存数据进行更改时,会通知缓存了该数据的CPU抛弃缓存数据或者从内存重新读取
- 总线锁
-
区别:
- 总线锁直接锁处理器,成本太高
- 缓存锁锁处理器的缓存行,
CPU
级的缓存一致性
(同volatile
可见性机制)
-
不会使用缓存锁的情况:
- 操作的数据不能被缓存在处理器内或数据跨多个缓存行
cache line
- 处理器不支持缓存锁
- 操作的数据不能被缓存在处理器内或数据跨多个缓存行
-
-
举例:
JUC
下的Atomic
类都是通过CAS
来实现的 -
缺点:
- 自旋时间太长(限制自旋次数:如
BlockingQueue
和SynchronousQueue
) - 只能保证一个共享变量原子操作(如果是共享变量使用
锁
) ABA
问题(解决:添加版本号
,采用AtomicStampedRdference
可实现)
- 自旋时间太长(限制自旋次数:如
参考地址: