CAS是什么?

  CAS的全称为Compare-And-Swap它是一条CPU并发原语,也就是在CPU硬件层面上来说比较并且判断是否设置新值这段操作是原子性的,不会被其他线程所打断。在JAVA并发包java.util.concurrent.atomic下底层所采用的就是利用CAS机制来避免进行并发计算时导致数据错乱问题。

atomic底层实现

java.util.concurrent.atomic下各个类主要使用UnSafe类来进行Compare-And-Swap操作。

Unsafe是Java中一个底层类,包含了很多基础的操作,比如数组操作、对象操作、内存操作、CAS操作、线程(park)操作、栅栏(Fence)操作,JUC包、一些三方框架都使用Unsafe类来保证并发安全。Unsafe类在jdk 源码的多个类中用到,这个类的提供了一些绕开JVM的更底层功能,基于它的实现可以提高效率。但是,它是一把双刃剑:正如它的名字所预示的那样,它是Unsafe的,它所分配的内存需要手动free(不被GC回收)。Unsafe类,提供了JNI某些功能的简单替代:确保高效性的同时,使事情变得更简单。

如果需要自定义原子引用则可以通过类AtomicReference通过泛型设置,本篇不做过多介绍。

接下来以AtomicInteger类为切入点来看看Atomic是如何利用Compare-And-Swap来保证并发安全。

public class AtomicInteger extends Number implements java.io.Serializable {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
//1.objectFieldOffset()方法用于获取某个字段相对Java对象的起始地址的偏移量。
//2.下次访问将直接通过this对象与相对偏移量直接从内存访问value的值。从不经过JVM虚拟机。
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
private volatile int value; .
.
.
//调用unsafe对预期值进行判断,如果判断成功则将值设置进去。
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
//调用unsafe.getAndAddInt方法,该方法内部采用自旋锁不断compareAndSet当设置成功后才跳循环,否则不断得查询并且计算然后进行compareAndSet。
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
public final class Unsafe {
.
.
.
public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
public native int getIntVolatile(Object var1, long var2);
//通过一个死循环不停的获取值并且计算然后比较是否能够设置否则继续如此操作。
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
//compareAndSwapInt是Unsafe类利用计算机底层实现的,该操作是具有原子性,所以不必担心并发问题。
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
}

CAS的缺点

因为CAS并不像synchronized锁住整个方法,其他线程会处于等待锁释放状态。所以CAS的并发性会增强。但是在并发性增强的同时也会伴随着一些缺陷。

  1. 循环时间长、CPU开销会增大。
  2. 只能保证一个共享变量的原子操作。
  3. 引出ABA问题。

ABA问题

假设有这么一个变量a其初始值为1,两个线程分别为线程A与线程B,线程A的调用周期远低于线程B。

顺序 线程A 线程B
1 a=getIntVolatile(0)
2 a=getIntVolatile(0)
3 this.compareAndSwapInt(var1, var2, a, 1)
4 a=getIntVolatile(1)
5 this.compareAndSwapInt(var1, var2, a, 0)
6 this.compareAndSwapInt(var1, var2, a, 2)

对于线程B是能够compareAndSwapInt成功的他无法感知到线程A将a变量设置为1后又设置为0的过程,线程B只关注结果,只要在执行compareAndSwapInt的时候预期值符合就能够将值设置进去。

ABA问题解决

解决ABA问题的其中思路就是引入版本号控制。对于每个compareAndSet成功的则版本号进行加1,然后每次拿着这个版本号去做期望值匹配,这样就能够避免ABA问题。所幸在java.util.concurrent.atomic包下同样有为我们提供已版本号为基础的原子引用操作类AtomicStampedReference。

//创建出AtomicStampedReference实例,参数分别为初始值和初始版本号
AtomicStampedReference<Integer> atomicStampedReference=new AtomicStampedReference(100,1);
//获取当前版本号
int stamp=atomicStampedReference.getStamp();
//执行比较并且设置参数分别为期望值,设置新值,期望版本号,设置新版本号
atomicStampedReference.compareAndSet(100,200,stamp,stamp+1)

java - CAS及CAS底层原理的更多相关文章

  1. Java并发容器,底层原理深入分析

    ConcurrentHashMap ConcurrentHashMap底层具体实现 JDK 1.7底层实现 将数据分为一段一段的存储,然后给每一段数据配一把锁, 当一个线程占用锁访问其中一个段数据时, ...

  2. JAVA框架 Spring AOP底层原理

    一:AOP(Aspect Oriented Programming)面向切面编程. 底层实现原理是java的动态代理:1.jdk的动态代理.2.spring的cglib代理. jdk的动态代理需要被代 ...

  3. java面试-CAS底层原理

    一.CAS是什么? 比较并交换,它是一条CPU并发原语. CAS是一种无锁算法,CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B.当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什 ...

  4. Java中的CAS原理

    前言:在对AQS框架进行分析的过程中发现了很多CAS操作,因此有必要对CAS进行一个梳理,也便更清楚的了解其原理. 1.CAS是什么 CAS,是compare and swap的缩写,中文含义:比较交 ...

  5. Java中的CAS实现原理

    一.什么是CAS? 在计算机科学中,比较和交换(Conmpare And Swap)是用于实现多线程同步的原子指令. 它将内存位置的内容与给定值进行比较,只有在相同的情况下,将该内存位置的内容修改为新 ...

  6. CAS底层原理与ABA问题

    CAS定义 CAS(Compare And Swap)是一种无锁算法.CAS算法是乐观锁的一种实现.CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B.当预期值A和内存值V相同时,将内存值V修 ...

  7. Java并发/多线程-CAS原理分析

    目录 什么是CAS 并发安全问题 举一个典型的例子i++ 如何解决? 底层原理 CAS需要注意的问题 使用限制 ABA 问题 概念 解决方案 高竞争下的开销问题 什么是CAS CAS 即 compar ...

  8. Java并发--Java中的CAS操作和实现原理

    版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/CringKong/article/deta ...

  9. Java锁与CAS

    一.加锁与无锁CAS 在谈论无锁概念时,总会关联起乐观派与悲观派,对于乐观派而言,他们认为事情总会往好的方向发展,总是认为坏的情况发生的概率特别小,可以无所顾忌地做事,但对于悲观派而已,他们总会认为发 ...

  10. 《Java并发编程的艺术》Java并发机制的底层实现原理(二)

    Java并发机制的底层实现原理 1.volatile volatile相当于轻量级的synchronized,在并发编程中保证数据的可见性,使用 valotile 修饰的变量,其内存模型会增加一个 L ...

随机推荐

  1. Nginx简介入门

    买了极客时间上陶辉的Nginx核心知识100讲,正在学.链接 Nginx 4个组成部分 二进制可执行文件 nginx.conf 配置文件 access.log error.log nginx 版本 M ...

  2. 【转载】s19文件格式详解

    来源:http://blog.csdn.net/xxxl/article/details/19494187 1.概述 为了在不同的计算机平台之间传输程序代码和数据,摩托罗拉将程序和数据文件以一种可打印 ...

  3. windows下python3使用pip安装scrapy提示安装失败

    我的环境:     python3.6,     win10,      原因:不能成功安装twisted,因为twisted与高版本的python有兼容问题. 解决:1,先下载twisted二进制文 ...

  4. C# checked unchecked

    static void CheckedUnCheckedDemo() { int i = int.MaxValue; try { //checked //{ // Console.WriteLine( ...

  5. 疫情之下,使用FRP实现内网穿透,远程连接公司电脑进行办公

    当前情况下,经常会有需要到公司电脑进行一些操作,比如连接内网OA,数据库或者提交文档.为了减少外出,将使用frp进行内网穿透的方法进行一个说明. 前提条件 1. 一台拥有公网 IP 的设备(如果没有, ...

  6. IoU-aware Single-stage Object Detector for Accurate Localization

    网络的结构如下: 采用FPN结构,Backbone是RetinalNet,分成了P3~P7共5个Layer,分别训练不同尺寸的Box.每个Layer对应的Head有2个分支,包括一个单独的分支用来预测 ...

  7. Python爬虫实战教程:爬取网易新闻;爬虫精选 高手技巧

    前言本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. stars声明很多小伙伴学习Python过程中会遇到各种烦恼问题解决不了.为 ...

  8. vue富文本编辑器vue-quill-editor使用总结(包含图片上传,拖拽,放大和缩小)

    vue-quill-editor是vue很好的富文本编辑器,富文本的功能基本上都支持,样式是黑白色,简洁大方. 第一步下载 vue-quill-editor: npm i vue-quill-edit ...

  9. C# Excel导出超出65536行报错 Invalid row number (65536) outside allowable range (0..65535)

    C# Excel导出超出65536行报错 Invalid row number (65536) outside allowable range (0..65535) 一:报错 Invalid row ...

  10. 浏览器对象模型“BOM”-- window对象

    global对象 全局对象 所有的全局变量和全局方法,都可以归在window上 <!DOCTYPE html> <html lang="en"> <h ...