深入理解Java并发编程(四):CAS操作以及jdk1.8后的优化

一、前言

说到CAS之前,先来看看乐观锁与悲观锁:

悲观锁认为:每个线程在对一数据进行操作时,都会有其他线程来并发修改,所以在获取数据的时候就上锁来进行操作,synchronized和lock就是一种悲观锁的策略。也就是先上锁再操作。

乐观锁认为:每个线程在对以数据进行操作时,没有其他线程来并发修改,这样就其实是所有线程都去读取共享区的数据,然后在本地工作内存操作,最后看共享区的数据有无被其他线程更新。如果没有则将修改后的数据写入,如果有的话就根据具体实现具体分析(报错或者自动重试)。即直接操作

我们不难得出:
悲观锁适合大量写操作的场景,先加锁可以保证写操作时数据的正确。
乐观锁适合大量读操作的场景,不加锁的特点能够使其读操作的性能大大提升。

二、什么是CAS操作

CAS操作,全称Compare and Swap,比较并交换。

CAS操作就是一个虚拟机实现的原子操作(一条硬件操作指令,不可被中断的一个或一系列操作),功能是将旧值替换为新值,如果旧值没有改变则替换成功,否则替换失败。

一般使用锁的时候,线程获取锁是一种悲观锁策略。即假设每一次在访问共享资源都会产生冲突,所以当前线程获取到锁的同时就会阻塞其他线程获取该锁。

CAS操作是一种乐观锁策略。它假设每一次在访问共享资源时都不会产生冲突,那不冲突就不会阻塞其他线程获取该锁,这样线程就不会出现阻塞停顿状态。Java使用CAS来鉴别线程是否出现冲突,出现冲突就重试当前操作直到没有冲突为止。线程只会收到操作失败的信号并进行原地自旋,并不会阻塞。

三、CAS操作的过程

CAS操作离不开这三个值(V, O, N):

  • V:内存地址存放的实际值
  • O:旧值
  • N:即将更新的新值

当且仅当VO相同时,即旧值和内存中实际存放的值相同,这表明该值没有被其他线程更改过,此时CAS通过原子的方式将N赋给V,并返回true。这是一个比较+更新操作,是原子操作。如果VO不相同,则该值已经被其他线程修改,不能把N赋给V,此时不进行操作,返回false。多个线程使用CAS操作一个变量时,只有一个线程会成功,并且成功更新,其余会失败(并不会阻塞其他线程)。失败的线程会重新尝试,也可以选择挂起线程。

synchronized存在线程竞争的情况下会出现线程阻塞和唤醒锁带来的性能问题,因为这是一种互斥同步(阻塞同步)。而CAS在竞争时如果失败,会进行一定的尝试,而并不是单纯的进行挂起唤醒操作,因此也叫非阻塞同步。

四、CAS的问题

CAS主要有以下三个问题:

1.ABA问题

CAS会检查共享内存的值有无变化,如果我们的共享内存值由A变成了B,可是又由B变回来了,此时CAS检查的时候发现共享内存的值并没有变化依然为A,但是实际上

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值