文章目录
- 1:何为CAS
- 2:CAS图示
- 3:CAS和Volatile的关系
- 4:为何CAS效率更高一些
- 5:CAS的特点
- 7:受保护得共享数据类型
- (1):原子基本数据类型
- (2):原子引用数据类型
- 7:ABA问题
- (1):什么是ABA
- (2):如何解决呢?
1:何为CAS
- CAS(Compare And Swap),即比较并交换。是解决多线程并行情况下使用锁造成性能损耗的一种机制。
- CAS操作包含三个操作数——内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。
- CAS有效地说明了“我认为位置V应该包含值A;如果包含该值,则将B放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。
2:CAS图示
- 我们对共享资源(balance)用 AtomicInteger修饰,调用其compareAndSet方法使每次更余额的时候,我们的余额都是最新值。
- 流程展示
解释:图示中的注释中线程2对共享变量的操作发生在 线程1 中 (int next = prev - amount 和 if …之间)在这其中发生了上下文切换。
3:CAS和Volatile的关系
- 获取共享变量时,需要用到volatile修饰变量,来保证变量的可见性;
- CAS必须借助volatile才能读取到共享变量的最新值,来实现比较交换。
4:为何CAS效率更高一些
- 无锁情况下,即使重试失败,线程始终在高速运行,没有停歇,而synchronized会让线程在没有获得锁的
时候,发生上下文切换,进入阻塞。打个比喻 - 线程就好像高速跑道上的赛车,高速运行时,速度超快,一旦发生上下文切换,就好比赛车要减速、熄
火,等被唤醒又得重新打火、启动、加速.恢复到高速运行,代价比较大 - 但无锁情况下,因为线程要保持运行,需要额外CPU的支持,CPU在这里就好比高速跑道,没有额外的
跑道,线程想高速运行也无从谈起,虽然不会进入阻塞,但由于没有分到时间片,仍然会进入可阻塞状
态,还是会导致上下文切换。
5:CAS的特点
结合CAS和volatile可以实现无锁并发,适用于线程数少、多核CPU的场景下。
- CAS是基于乐观锁的思想:最乐观的估计,不怕别的线程来修改共享变量,就算改了也没关系,我吃亏
点再重试呗。 - synchronized是基于悲观锁的思想:最悲观的估计,得防着其它线程来修改共享变量,我上了锁你们都别
想改,我改完了解开锁,你们才有机会。 - CAS体现的是== 无锁并发、无阻塞并发 == ,请仔细体会这两句话的意思
- 因为没有使用synchronized,所以线程不会陷入阻塞,这是效率提升的因素之一
- 但如果竞净激烈,可以想到重试必然频繁发生,反而效率会受影响(这里的重试就是,pre值和内存值不一样,CAS返回的结果false,那么的话我们再进行一次CAS操作)
7:受保护得共享数据类型
(1):原子基本数据类型
(2):原子引用数据类型
7:ABA问题
(1):什么是ABA
本来主线程从主存中获取到的值是A,然后我们进行CAS中的比较也是和主存中的A进行比较,但是如果有线程在主线程CAS操作之前将A改为B,又将B改为A的话,那么主线程是感知不到的。
(2):如何解决呢?
如果主线程希望只要有其他线程动过了,共享变量的话,那么自己的CAS操作就算失败,这时仅仅是比较值是不够的,还要增加一个版本号,只要有人动过共享变量的话,那么版本号就会发生相应的变化,一旦主线程发现版本号不同的话,那么我们就CAS操作失败