Java的CAS(比较交换)

一、什么是CAS

使用锁时,线程获取锁是一种悲观锁策略,而CAS操作(又称为无锁操作)是一种乐观锁策略,使用CAS(compare and swap)又叫做比较交换来鉴别线程是否出现冲突,出现冲突就重试当前操作直到没有冲突为止。

CAS:Compare And Swap(比较交换机制)——乐观锁策略

悲观锁(如JDK1.6之前的内建锁):假设每一次执行同步代码块均会产生冲突,所以当线程获取锁成功,会阻塞其他尝试获取该锁的线程

乐观锁(如Lock):假设所有线程访问共享资源时不会出现冲突,既然不会出现冲突自然就不会阻塞其他线程。线程不会出现阻塞状态。

CAS(无锁操作):使用CAS叫做比较交换来判断是否出现冲突,出现冲突就一直重试当前操作,直到不冲突为止。

二、CAS的操作过程

一般来说,CAS交换过程有三个阶段V、O、N

V;内存中地址存放的实际值

O:预期值(旧值)

N:新值,表示我们准备更新V的值

当执行CAS后,如果V == O ,即旧值与内存中实际值相等,表示上次修改后没有任何线程再次修改此值,因此可以将N替换到内存中。

如果  V != O,表示该内存中的值已经被其他线程做了修改,所以无法将N替换,返回最新的值V

当多个线程使用CAS操作一个变量时,只有一个线程会成功,并成功更新变量值,其他线程均会失败。失败线程会重新尝试或将线程挂起(阻塞)

三、CAS存在的问题

1.ABA问题:一个旧值A变为了成B,然后再变成A,刚好在做CAS时检查发现旧值并没有变化依然为A,但是实际上的确发生了变化。

解决思路:沿用数据库的乐观锁机制,添加版本号1A-2B-3A,JDK1.5提供atomic包下AtomicStampedReference类来解决CAS是ABA问题

2.自旋(不断重试)会浪费大量的处理器资源

与线程阻塞相比,自旋会浪费大量的cpu资源。因为此时线程仍处于运行状态,只不过跑的是无用指令,期望在无用指令时,锁能被释放出来。

解决思路:自适应自旋,根据以往自旋等待时能否获取到锁,来动态调整自旋时间(循环尝试数量)

具体策略:如果在上一次自旋时获取到锁,则此次自旋时间稍微变长一点;如果在上一次自旋结束还没有获取到锁,此次自旋时间稍微短一点。

3.公平性

处于阻塞状态的线程无法立刻竞争被释放的锁;而处于自旋状态的线程很有可能先获取到锁。内建锁无法实现公平性,而lock体系可以实现公平锁。

四、元老级的内建锁(Synchronized)最主要的问题:

   线程存在竞争的情况下会出现线程阻塞以及唤醒带来的性能问题,是一种互斥同步(阻塞同步),效率很低

   而CAS并不是武断的将线程挂起,会尝试若干次CAS操作,并非进行耗时的挂起与唤醒操作,因此是非阻塞式同步

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值