在介绍 CAS 之前,先来了解下什么是乐观锁。

乐观锁(Optimistic Lock)是指对于数据冲突保持一种乐观态度,操作数据时不会对数据加锁,只有到数据提交的时候才通过某种机制来验证数据是否存在冲突。

可以通过使用版本号CAS 算法进行实现,本篇博客主要介绍 CAS 算法的概念,以及对 CAS 算法的实现原理进行分析。

什么是 CAS 算法

CAS:Compare and Swap,即比较再交换,其算法公式如下:

函数公式:CAS(V,E,N)

CAS 操作需要我们提供一个期望值,当期望值与当前线程的变量值相同时,说明还没有线程修改该值,当前线程就可以进行修改,也就是执行 CAS 操作。

但如果期望值与当前线程的变量值不符,则说明该值已被其他线程修改,此时不执行更新操作,但可以选择重新读取该变量并尝试再次修改,也可以放弃操作。

CAS 的实现原理

对 java.util.concurrent.atomic 包下的原子类 AtomicInteger 中的 compareAndSet 方法进行分析,可以发现最终调用的是 sum.misc.Unsafe 这个类。

    /*** Atomically sets the value to the given updated value* if the current value {@code ==} the expected value.** @param expect the expected value* @param update the new value* @return {@code true} if successful. False return indicates that* the actual value was not equal to the expected value.*/public final boolean compareAndSet(long expect, long update) {return unsafe.compareAndSwapLong(this, valueOffset, expect, update);}

Unsafe 类本身是不安全的,它为了速度,在 Java 的安全标准上做出了一定的妥协。Unsafe 的 CAS 依赖的是 JVM 针对不同的操作系统实现的 Atomic::cmpxchg 函数。

Atomic::cmpxchg 函数使用了汇编的 CAS 操作,并使用 CPU 硬件提供的 lock 信号保证其原子性的实现。

CAS 的优缺点

优点

CAS 是非阻塞的轻量级乐观锁,通过 CPU 指令实现。在资源竞争不激烈的情况下,synchronized 重量锁会进行比较复杂的加锁、解锁和唤醒操作,而 CAS 不会加锁,性能高。

缺点

CPU开销大

在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量却又一直更新不成功,会给 CPU带来很大压力。

不能保证代码块的原子性

CAS 机制所保证的只是一个变量的原子性操作,而不能保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新,就不得不使用 synchronized 同步锁了。

除了以上两个缺点,CAS 还可能会出现 ABA 的问题,那么 ABA 问题又是什么呢?

CAS 中的 ABA 问题

如果一开始位置 V 得到的旧值是 A ,当进行赋值操作时再次读取发现仍然是 A ,并不能说明变量没有被其它线程改变过,有可能是其它线程将变量改为了 B,后来又改回了 A。

对于 ABA 问题,主要有两种解决方案:

使用版本号

在变量前面追加版本号,每次变量更新的时候把版本号加一,也就是说,之前的 A-B-A 就会变成 1A - 2B - 3A。

使用并发包的原子类

java.util.concurrent.atomic 包下提供了一个可处理 ABA 问题的原子类 AtomicStampedReference。其 compareAndSet 方法首先会检查当前引用是否等于预期引用,且当前标志是否等于预期标志。

如果全部相等,则以原子方式将该引用的该标志的值设置为给定的更新值。

CAS 的使用场景

  • Atomic 开头的实现类

以 Atomic 开头的实现类的底层都使用了 CAS 算法。

  • 自旋锁

自旋锁是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程不会阻塞,而是将循环等待,不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。可以看成是一个不断自动重试的乐观锁,它是 CAS 算法的一种锁机制的实现。

  • 令牌桶限流器

系统以恒定的速度向桶内增加令牌,每次请求前从令牌桶里面获取令牌,只有获取到令牌就才可以进行访问。

当令牌桶内没有令牌的时候,就会拒绝提供服务。其中的限流器就是通过使用 CAS 算法来维护多线程环境下对令牌的增加和分发的。

参考了如下博客,非常感谢:

Java并发编程之CAS算法

java中的cas - 知乎

乐观锁实现之CAS算法分析相关推荐

  1. 乐观锁,CAS,ABA问题

    文章目录 常见的锁策略 乐观锁 vs 悲观锁 读写锁 自旋锁(Spin Lock) 可重入锁 什么是 CAS CAS 是怎么实现的 ABA 问题(乐观锁导致的) synchronized 锁 常见的锁 ...

  2. 【java】乐观锁和悲观锁、CAS和ABA问题

    一.乐观锁VS悲观锁 1)关于悲观锁 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,Java中synchronized和ReentrantLock以及Read ...

  3. 面试官问:说说悲观锁、乐观锁、分布式锁?都在什么场景下使用?有什么技巧?...

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 如何确保一个方法,或者一块代码在高并发情况下,同一时间只能 ...

  4. 说说悲观锁、乐观锁、分布式锁

    作者 | 张飞洪 来源 | https://www.cnblogs.com/jackyfei/p/12142840.html 如何确保一个方法,或者一块代码在高并发情况下,同一时间只能被一个线程执行, ...

  5. 乐观锁与悲观锁及其实现

    乐观锁与悲观锁及其实现 乐观锁  每次操作时不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止 悲观锁  是会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁. 乐观锁可 ...

  6. 【mysql】悲观锁和乐观锁的实现原理

    java多线程中的锁分类多种多样,其中有一种主要的分类方式就是乐观和悲观进行划分的. 一.乐观锁概念 说是写乐观锁的概念,但是通常乐观锁和悲观锁的概念都要一块写.对比着来才更有意义. 1.悲观锁概念 ...

  7. zbb20180929 thread 自旋锁、阻塞锁、可重入锁、悲观锁、乐观锁、读写锁、对象锁和类锁...

    1.自旋锁 自旋锁可以使线程在没有取得锁的时候,不被挂起,而转去执行一个空循环,(即所谓的自旋,就是自己执行空循环),若在若干个空循环后,线程如果可以获得锁,则继续执行.若线程依然不能获得锁,才会被挂 ...

  8. Java之原子性-乐观锁与悲观锁

    1.volatile-问题 1.1.代码分析 : package com.itheima.myvolatile;public class Demo {public static void main(S ...

  9. 乐观锁 VS 悲观锁

    乐观锁 VS 悲观锁 悲观锁:总是假设最坏的情况,每次取数据时都认为其他线程会修改,所以都会加锁(读锁.写锁.行锁等),当其他线程想要访问数据时,都需要阻塞挂起. 乐观锁:总是认为不会产生并发问题,每 ...

  10. Java悲观锁与乐观锁

    Java悲观锁与乐观锁 锁的目的 实例 悲观锁实现 乐观锁实现 总结 锁的目的 多线程编程如有共用资源的使用时,需要保证数据安全,资源需要同步处理.处理资源的手段可以有:互斥同步与非阻塞同步.实现分别 ...

最新文章

  1. mysql数据库开发规范_开发规范——MYSQL数据库
  2. linux中bash的功能主要有,Linux系统中的Bash功能的介绍
  3. java真的是值传递么?
  4. (转载)网络编程释疑之:同步,异步,阻塞,非阻塞
  5. java excutorthread_Java中ThreadPoolExecutor的参数理解
  6. 自动论文生成器 python_python生成器
  7. 2021-06-16异步调用 CompletableFuture
  8. Boblog热门日志、随机日志、热门Tags插件源代码
  9. 商业计划书(BP)应该包含哪些点?看 BP 的人最想从中得到什么?
  10. 华为当个pl怎么样_华为8PL∪S提示灯 | 手游网游页游攻略大全
  11. python背景颜色代码大全_Python实现转换图片背景颜色代码
  12. GooglTest GoogleMock 实践感想三 死亡测试初步(1)
  13. r语言实现岭回归_R语言回归篇
  14. 网页形式的php抓取文件,PHP 抓取网页源文件
  15. Kubernetes切换Docker容器引擎为Containerd
  16. vue cli3 配置sass全局变量设置不生效,sass混合器文件全局引入
  17. html五角星代码,五角星评分系统.html
  18. Hadoop:MapReduce编程之统计每个订单价格最高的商品信息
  19. 这种动态条形图+折线图怎么做?今天我来教你!
  20. UVALive 4513 Stammering Aliens

热门文章

  1. 最新iOS面试题:APP性能优化(①系列更新)
  2. 第二章 基于QT和DCMTK的Dicom 图像浏览器---界面设计
  3. 用Java实现24点游戏
  4. 公网远程Everything快速搜索私有云资料【内网穿透】
  5. android蓝牙取sbc音频数据
  6. t-SNE可视化-Python实现
  7. QT实现的人机对战五子棋
  8. 【嗅探工具】wireshark初步认识
  9. python pygame实现简单的网游 1
  10. python 视频解析接口_python接口自动化测试视频教程全集