cas无法使用_点开之前没想到 CAS 原理这么简单

d5a0610a5ef4bcdf67c9d5b1b4a0e6fd.png

不知道大家有没有这样的感受:每当遇到一个新概念,特别是英文简称,觉得“高深莫测”,挺 NB 的亚子。

比如 JMM,CTL,ACK,JMS ,RPC,REST,CAS 和 ASQ 等。

382de398b9a5481f3e78687ae1ea9264.png

多次运行,我们发现使用 AtomicInteger ,最后输出的结果是 100000,和 synchronized 一样保证了原子性。

AtomicInteger 的底层,正是利用了【CAS机制】。

CAS (Compare And Swap的缩写)

比较并替换

CAS 机制当中使用了 3 个基本操作数:

内存值 V,旧的预期值 A,需要修改的新值 B。

474aa9e6f39f3f8a4c2f40657a617c1e.png
比较 A 与 V 是否相等。(比较) 如果比较相等,将 B 写入 V。(交换) 返回操作是否成功。

当 n 个线程同时对某个共享资源进行 CAS 操作,只有 1 个线程操作成功,不会和 synchronized 阻塞其他线程,其他线程只会收到操作失败的信号。CAS 是一个乐观锁。

AtomicInteger 的自增方法 incrementAndGet

62f333d0943831fdc3ff456cc4df485e.png

我们可以看到代码中使用了 do...while 循环,一个无限循环中,执行一个 CAS 操作,当操作成功,返回 true 时,循环结束;当返回 false 时,接着执行循环,继续尝试 CAS 操作,直到返回 true。

CAS的缺点:

① ABA 问题,如果内存中的数据从 A 变成 B,又变成 A ,CAS 操作无法识别数据的变化。使用带版本号的原子引用 AtomicStampedRefence,或者叫时间戳的原子引用,类似于乐观锁。

场景一:

假设你的话费余额是 100 元,有个游戏扣费业务(资费 50 元)由于故障发起了 2 次扣款,如果使用 CAS 操作,第一次成功扣款 50元,这时,你亲爱的老妈给你充了 50元,第二次扣款发现 内存值和旧的预期值相等,于是又扣了 50 元,话费余额又变成 50 元。

cf07af4be03742033d702a4e77eaecf8.gif

场景二:比如单向链表 A->B,表头是 A,此时线程 t1 想把 表头换成 B,但是线程 t2 将链表改成 A->C->D,由

线程 t1 判断表头还是 A,会丢失 C 和 D.

bf344bc7a9fb1f42c81777bfdefde698.png
8ce095ff36f190538aed0170dbbb7b57.png

② 不能保证代码块的原子性

CAS只是保证一个变量的原子性操作,如果涉及到代码块,可以使用 synchronized。

③ CPU 开销较大

高并发下,如果 n 个线程 CAS 操作一直处于 while 循环中,CPU开销很大,在并发量不是很高时cas机制会提高效率。


欢迎关注 @Python大星,一个会点 Python 的 Java 程序员。如文章描述有问题,评论下欢迎留言,有问题,你就说。

@Python大星 | 文

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值