CAS、volatile是JUC包实现同步的基础。Synchronized下的偏向锁、轻量级锁的获取、释放,lock机制下锁的获取、释放,获取失败后线程的入队等操作都是CAS操作锁标志位、state、队列完成的。

CAS过程

CAS的全称是Compare And Swap 即比较交换 ,是系统原语,由一系列系统的指令组成,不可被分割,简单的说就是CAS操作时一个原子性的操作。在sun.misc.unsafe类中,所有方法都是native的,都直接调用操作系统底层资源执行相应任务,比如直接操作内存,Java中CAS操作的执行依赖于Unsafe类的方法。其算法核心思想如下

其包含3个参数

  • V表示要更新的变量(即内存中的某变量的当前值)

  • E表示预期值

  • N表示新值

CAS操作需要我们提供一个期望值E,当 E == V 时,说明还没线程修改该值,当前线程可以进行修改为N,但如果期望值与当前线程不符,则说明该值已被其他线程修改,此时不执行更新操作,但可以选择重新读取该变量再尝试再次修改该变量 (也叫自旋) ,也可以放弃操作。

CAS的ABA问题

虽然CAS可以用很小的开销完成某些需要同步的操作,但也存在一些问题,比如ABA问题,并发量大的情况下自旋消耗过大的问题。关于ABA问题,举例说明:

我买东西付款100元后,由于一些原因,发起了两个付款线程 1、2。线程1 预期我的账户内存中的值为A元钱,要把它-100修改为B元。

这时线程1阻塞了,线程2顺利执行把A改为B。(正常情况下,线程1应该是CAS失败的,因为内存值B以经不等于它的预期值A了)

线程1还没来得及继续执行,你给我转账100元,并且这个转账 线程3 顺利执行完毕,我的账户+100,又变成A元。

在转账线程3完成后,线程1终于又开始执行了,它发现内存值还是A,于是它会执行扣款操作。我平白无故损失100元。

简单的说,ABA问题是: 两个进行同样操作的线程,本来是应该只能有一个操作成功,但是由与第三者介入二者之间修改数据,迷惑了二者中后执行的线程,使两个线程同样的操作都执行成功了。  比如扣了两次款!

解决办法是给我的余额值加个版本号,经过一次修改就更新一次版本。对于有些情况, 预期中的值、版本号 == 内存中值、版本号, 即二者都想等,才执行更新操作。

最新文章

  1. Android 自定义title 之Action Bar
  2. 转载几篇关于GNU autotools的文章
  3. centreon 画图x轴乱码
  4. 一些Swift编程语言的相关资料
  5. Android LinearLayout中weight属性的意义与使用方式
  6. Structual设计--Flyweight模式
  7. Jobbox.io(职位盒子): 新兴的面向技术人才的职场招聘众推平台
  8. @Transactional注解详解
  9. 小米官网的css3导航菜单
  10. Caffe源码理解1:Blob存储结构与设计
  11. 【重学计算机】机组D6章:中央处理器
  12. Python基础:语法基础(3)
  13. hdu:2036.改革春风吹满地
  14. elasticsearch 之编译过程
  15. Linux系统数据共享-NFS服务
  16. 线程封装组件(BackgroundWorker)和线程(Thread)
  17. python之字典操作
  18. 【linux】之常用命令-杂项
  19. HDU 2102 A计划(BFS/DFS走迷宫)
  20. IntelliJ IDEA 自动导入包的问题

热门文章

  1. java - 数组与String的length方法问题
  2. Codeforces Round #486 (Div. 3) C "Equal Sums" (map+pair<>)
  3. 【Android】Field requires API level 4 (current min is 1): android.os.Build.VERSION#SDK_INT
  4. QScintilla下载与编译
  5. poj 1131 Octal Fractions(高精度小数进制转换) Java
  6. RocketMQ中NameServer的启动
  7. maven 下载 安装 环境配置
  8. 开发一个Spring Boot Starter!
  9. 解决Activiti5.22流程图部署在Windows上正常,但在linux上部署后出现中文变方块的问题
  10. 【数据结构学习】关于HashMap的那些事儿