多线程透析-CAS

多线程透析-CAS

研究过多线程锁的想必都是知道CAS。

什么是CAS?
CAS (Compare And Swap):比较并交换。是一种轻量级锁的实现方式,也被称为乐观锁。锁的原理就是不会真实的去添加锁,而是通过频繁的去探测访问资源进行比较,直达资源可用进行交换操作。

老规矩还是举例说明:
现在有多个线程a,b,c要对公共资源count进行++操作。

按照之前学习的内容在处理这个程序的时候我们会想到synchronize 和 juc 进行操作,以保障多线程的三大特性(原子性、有序性、可见性–后续详细透析)。

先说说CAS的实现原理,后面再分析synchronize 和juc

CAS实现原理:
在这里插入图片描述
CAS: 全称:Compare And Swap 或者Compare And exchange 比较和交换。
当a,b,c三个线程都对count进行数据++操作时。
在这里插入图片描述
一开始a,b,c都会从内存中拿到数据都是1,这个时时候,a,b,c三者都进行了++操作,都变成了2.
然后都将写入到count里面。
在这里插入图片描述
假如a线程进行操作了,再写入count之前需要做一些操作:比较。就是比较这个count 数据是不是依旧为1(取过来的值),如果依旧是1,那么就把2写入进去。如果正好其他线程已经把count改成3了。
a发现count不在是1了,那么他会把3都读取过来进行++操作,再往回写的时候,再判断count是否为3…一直反复着这样的操作过程就是CAS实现原理。

通过以上透析我们会发现两个问题?

  1. 如果这个count
    被其他线程改成了3,然后又被另一个线程改回了1,那么问题就是现在这个1已经不是a开始读的那个1了,这个就是CAS的一个称为ABA问题
    —> 那这个怎么解决的呢?很简单就是将每次读取的数据加上版本号进行识别。

  2. 还有个问题,就是如果a在计算完往回写入的时候,已经做完了比较,正准备写的过程中count被其他线程改了怎么办?这个问题就是线程原子性问题。
    ----> 这个是怎么解决的呢? 这个就要去研究CAS源码了,在底层中有个lock.cmpxchg是代码。lock是jvm提供的解决原子性问题的,它是一个锁总线,在线程操作为结束的时,不能被其他线程打断。

以上就是CAS的一个实现原理和问题的解决办法。

JDK在1.1~1.2版本的时候用的synchronize,那个时候synchronize只是一个重量级锁 | 悲观锁,之前介绍过,重量级锁是通过OS进行的线程调度接管,所以效率会慢。

于是呢,在JDK1.5之后推出了JUC包,这个包提供了很多原子类都是基于CAS。例如:static AtomicInteger value2 = new AtomicInteger(0);
核心代码:
在这里插入图片描述
可以看到CAS有两个核心的参数(期望值expect、更新值update)
JUC(后面说)。

之后再JDK1.6之后就对synchronize进行了优化,引入了所升级的概念,后面也会详细介绍。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Survivor001

你可以相信我,如果你愿意的话

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值