CAS及其ABA问题
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问题是: 两个进行同样操作的线程,本来是应该只能有一个操作成功,但是由与第三者介入二者之间修改数据,迷惑了二者中后执行的线程,使两个线程同样的操作都执行成功了。 比如扣了两次款!
解决办法是给我的余额值加个版本号,经过一次修改就更新一次版本。对于有些情况, 预期中的值、版本号 == 内存中值、版本号, 即二者都想等,才执行更新操作。
CAS及其ABA问题的更多相关文章
- 沉淀再出发:java中的CAS和ABA问题整理
沉淀再出发:java中的CAS和ABA问题整理 一.前言 在多并发程序设计之中,我们不得不面对并发.互斥.竞争.死锁.资源抢占等等问题,归根到底就是读写的问题,有了读写才有了增删改查,才有了所有的一切 ...
- java并发编程(十三)----(JUC原子类)引用类型介绍(CAS和ABA的介绍)
这一节我们将探讨引用类型原子类:AtomicReference, AtomicStampedRerence, AtomicMarkableReference.AtomicReference的使用非常简 ...
- Java高性能编程之CAS与ABA及解决方法
Java高性能编程之CAS与ABA及解决方法 前言 如果喜欢暗色调的界面或者想换换界面,可以看看我在个人博客发布的 Java高性能编程之CAS与ABA及解决方法. CAS概念 CAS,全称Compar ...
- CAS的ABA问题详解
CAS的ABA问题详解 ABA问题 在多线程场景下CAS会出现ABA问题,关于ABA问题这里简单科普下,例如有2个线程同时对同一个值(初始值为A)进行CAS操作,这三个线程如下 1.线程1,期望值为A ...
- CAS 和 ABA 问题
CAS简介 CAS 全称是 compare and swap,是一种用于在多线程环境下实现同步功能的机制. CAS 它是一条CPU并发原语.操作包含三个操作数 -- 内存位置.预期数值和新值.CAS ...
- Java并发编程入门与高并发面试(三):线程安全性-原子性-CAS(CAS的ABA问题)
摘要:本文介绍线程的安全性,原子性,java.lang.Number包下的类与CAS操作,synchronized锁,和原子性操作各方法间的对比. 线程安全性 线程安全? 线程安全性? 原子性 Ato ...
- Java CAS 和ABA问题
独占锁:是一种悲观锁,synchronized就是一种独占锁,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁. 乐观锁:每次不加锁,假设没有冲突去完成某项操作,如果因为冲突失败就重试,直到成功 ...
- 无锁编程(四) - CAS与ABA问题
CAS 一般采用原子级的read-modify-write原语来实现Lock-Free算法,其中LL和SC是Lock-Free理论研究领域的理想原语,但实现这些原语需要CPU指令的支持,非常遗憾的是目 ...
- 谈论高并发(十二)分析java.util.concurrent.atomic.AtomicStampedReference看看如何解决源代码CAS的ABA问题
于谈论高并发(十一)几个自旋锁的实现(五岁以下儿童)中使用了java.util.concurrent.atomic.AtomicStampedReference原子变量指向工作队列的队尾,为何使用At ...
随机推荐
- 记一次远程CMD开发过程
开发初衷: 有些同学电脑老是要出问题,但又不是什么大问题,通常几句cmd就能搞定.之前解决方案有2:一是远程演示,我口述别人操作:一是我写个cmd脚本,但毕竟不在本机不好调试.(吐槽一下常用的远程控制 ...
- 程序员的长安十二时辰:Java实现从Google oauth2.0认证调用谷歌内部api
最近公司在做一个app购买的功能,主要思路就是客户在app上购买套餐以后,Google自动推送消息到Java后端,然后Java后端通过订单的token获取订单信息,保存到数据库. Java后端要获取订 ...
- 基于 HTML5 Canvas 的可交互旋钮组件
前言 此次的 Demo 效果如下: Demo 链接:https://hightopo.com/demo/comp-knob/ 整体思路 组件参数 绘制旋钮 绘制刻度 绘制指针 绘制标尺 绘制文本 1. ...
- 使用hexo中遇到的问题
- QQ第三方登录逻辑(微信,微博等同)
实现过程:生成qq扫码登录连接(需要注册,链接里有几个参数需要按照开发文档的格式进行拼接,要后端完成),点击QQ登录按钮,前端Vue发送axios请求,后端收到请求把生成的QQ登录链接发送给vue,v ...
- Js面向对象原型~构造函数
脑袋一团浆糊,但希望写点啥,所有就有了这篇博文了,抱歉哦....开始吧!!!! 什么是构造函数?? 所谓"构造函数",其实就是一个普通函数,但是内部使用了this变量.对构造 ...
- 再记一次经典Net程序的逆向过程
1.前言 上次发完,有网友问了一个问题:如果不绕过编译,而是直接编译怎么办? 记一次Net软件逆向的过程:https://www.cnblogs.com/dotnetcrazy/p/10142315. ...
- Java中Timer和TimerTask来实现计时器循环触发
package xian; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.Fi ...
- 大数阶乘(c++实现)
#include <iostream>using namespace std;#define N 1000int BigNumFactorial(int Num[], int n);voi ...
- 二、Markdown基本语法
目录 2.1 标题 一级标题 二级标题 三级标题 2.2 加粗 2.3倾斜 2.4 高亮 2.5 上标 2.6 下标 2.7 代码引用(>式) 2.8 代码引用(```式) 2.9 代码引入(` ...