CAS(Compare And Swap)

之前的文章讲了ReentrantLocksynchronized都是通过锁来保证线程安全的,锁机制存在一些问题,例如:

  ? 在多线程的竞争下,加锁、释放锁会导致很多线程的上下文切换和调度,对性能有一定的影响;

  ? 一个线程持有锁会导致其他需要此锁的线程挂起(强行在锁的区域将并行变为串行);

  ? 使用不当还会导致死锁、饥饿、活锁等;

也许你会说,也可以用volatile,volatile是轻量级的锁,但是不能保证原子性,所以最后还是会回到锁的机制上来;

synchronized和ReentrantLock都是独占锁,独占锁是一种悲观锁,会导致其余需要锁的线程挂起,等待持有锁的线程释放锁的资源,并且每次只能有一个线程执行;而另一个更加有效的锁就是乐观锁,乐观锁就是乐观的认为每次操作都没有冲突,如果有,则重试,直到成功为止,乐观锁使用到的机制就是CAS。

CAS(Compare And Swap)

CAS:Compare and Swap 即:比较并交换。设计并发计算时常用到的一种技术,java.util.concurrent包的基础建立在CAS之上,没有CAS就没有此包,可见CAS的重要性。

在Java语言出现之前,并发就已经广泛存在并在服务器领域得到了广泛的应用。所以硬件厂商很早就在芯片中加入了大量支持并发操作的原语,从而使硬件性能得到提升,在Intel中,采用的是cmpxchg指令。

在Java的发展初期,Java语言是不能利用硬件提供的这些便利来提升系统的性能的,随着Java的发展,JNI(Java Native Interface)的出现,使得Java程序可以越过JVM直接调用本地(本机)上的一些方法,这样不仅使得Java在并发上的手段增多了,同时也提高了Java系统的性能。

CAS有三个操作数:内存值V,旧的预期值A、要修改的新值B,当且仅当预期值A和内存值V相同时,将内存值修改为B并返回true,否则什么都不做并返回false。

CAS是通过Unsafe类来实现的,下面看看Unsafe里的方法:

public final native boolean compareAndSwapObject(Object paramObject1, long paramLong, Object paramObject2, Object paramObject3);

public final native boolean compareAndSwapInt(Object paramObject, long paramLong, int paramInt1, int paramInt2);

public final native boolean compareAndSwapLong(Object paramObject, long paramLong1, long paramLong2, long paramLong3);

上面这三种方法都是Native本地方法,而且都是原子操作(硬件保证)。第一个参数表示需要更新的对象,第二个long表示的是该对象在内存中的偏移地址,第三个是预期值(即旧值),第四个是新值。

下面我们通过AtomicInteger来增加对CAS的理解,先来看AtomicInteger的类的变量定义,源码如下:

 1 private static final Unsafe unsafe = Unsafe.getUnsafe();
 2     private static final long valueOffset;
 3
 4     static {
 5       try {
 6         valueOffset = unsafe.objectFieldOffset
 7             (AtomicInteger.class.getDeclaredField("value"));
 8       } catch (Exception ex) { throw new Error(ex); }
 9     }
10
11     private volatile int value;

上述代码解释:

  ? Unsafe是CAS的核心。

  ? valueOffset是变量在内存中的偏移地址,因为Unsafe就是根据偏移地址去获取数据的原值的;

  ? value是volatile关键字修饰的,这个非常重要,这保证了变量在线程中的可见性;

再来看一个方法incrementAndGet(),源码如下:

public final int incrementAndGet() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return next;
        }
    }

public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

incrementAndGet()该方法每次增加1,并返回增加后的值。相当于++i的功能,但是++i不是原子性的,incrementAndGet()是原子性的。

从上述代码可以看出,incrementAndGet()方法内是一个死循环,保证了value一定会+1成功并返回,利用unsafe.compareAndSwapInt(this, valueOffset, expect, update)保证了对于value修改的线程安全性。

CAS的缺点

  1.存在ABA情况。CAS在操作时,需要比较值有没有发生变化,没有变化则更新,如果一个变量由A变成了B,再由B变回了A,那么CAS在检查时,就是发现该变量的值没有发生改变,但是实际上却变化了。从Java1.5开始。JDK在atomic提供了一个AtomicStampedReference类来解决ABA问题,这个类的compareAndSet(expectedReference, newReference,expectedStamp, newStamp)方法,会首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子的方式将该引用和该标志的值修改为给定的新值。

  2.循环时间长开销大。自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销。

  3.只能保证一个共享变量的原子操作。当对一个共享变量进行操作时,我们可以采用CAS方式来保证变量的线程安全,当有多个变量时,CAS就无法保证操作的原子性了,这个时候就只能用锁或者采用AtomicReference类来保证引用对象之间的原子性,AtomicReference支持把多个变量放到一个对象里进行CAS操作。

原文地址:https://www.cnblogs.com/Joe-Go/p/9771452.html

时间: 2024-10-10 08:14:03

CAS(Compare And Swap)的相关文章

Java多线程和并发(十一),CAS(Compare and Swap)

目录 1.CAS简介 2.CAS多数情况下对开发者来说是透明的 3.CAS缺点 十一.CAS(Compare and Swap) Synchronized直观意义上是一种悲观锁 cas则是乐观锁的一种体现 1.CAS简介 2.CAS多数情况下对开发者来说是透明的 3.CAS缺点 原文地址:https://www.cnblogs.com/xzmxddx/p/10362858.html

27、Java并发性和多线程-CAS(比较和替换)

以下内容转自http://ifeve.com/compare-and-swap/: CAS(Compare and swap)比较和替换是设计并发算法时用到的一种技术.简单来说,比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替换当前变量的值.这听起来可能有一点复杂但是实际上你理解之后发现很简单,接下来,让我们跟深入的了解一下这项技术. CAS的使用场景 在程序和算法中一个经常出现的模式就是“check and act”模式.先检查后操作模

CAS(Compare and Swap)理解

什么叫CAS(Compare and Swap)?  硬件同步原语!! 什么蛋疼的名字,一般人很难理解.根据英文全称翻译==比较与交换,这个名字大致还能理解一点,目前先暂且这么理解吧. 有啥用处? 对于常用多线程编程的人估计知道,对于一般人估计都不曾听说.在jdk5之前,我们知道,在多线程编程的时候,为了保证多个线程对一个对象同时进行访问时,我们需要加同步锁synchronized,保证对象的在使用时的正确性,但是加锁的机制会导致如下几个问题 1.加多线程竞争下,加锁和释放锁会导致较多的上下文切

Java基础知识强化(用于自我巩固)以及审查

1. Java 和 JDK 的关系 JDK(Java Development Kit)Java 开发工具包,它包括:编译器.Java 运行环境(JRE,Java Runtime Environment).JVM(Java 虚拟机)监控和诊断工具等 Java 则表示一种开发语言. 2. Java 程序是怎么执行的? 日常工作中使用的开发工具(IntelliJ IDEA 或 Eclipse 等)可以很方便的调试程序,或者是通过打包工具把项目打包成 jar 包或者 war 包,放入 Tomcat 等

Compare And Swap(CAS)实现无锁多生产者

1.CAS 原理 compare and swap,解决多线程并行情况下使用锁造成性能损耗的一种机制,CAS操作包含三个操作数--内存位置(V).预期原值(A)和新值(B).如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值.否则,处理器不做任何操作.无论哪种情况,它都会在CAS指令之前返回该位置的值.CAS有效地说明了"我认为位置V应该包含值A:如果包含该值,则将B放到这个位置:否则,不要更改该位置,只告诉我这个位置现在的值即可. 当同时存在读写线程时,默认情况下是不保证线

CAS(Compare And Swap)分析

CAS(Compare And Swap)指的是现代CPU广泛支持的一种对内存中的共享数据进行操作的一种特殊指令.这个指令会对内存中的共享数据做原子的读写操作. 简单介绍一下这个指令的操作过程:首先,CPU会将内存中将要被更改的数据与期望的值做比较.当这两个值相等时,CPU才会将内存中的数值替换为新的值,否则便不做操作.最后,CPU 会将当前变量的真实值返回.这一系列的操作是原子的. CAS是一种乐观锁的思路,它相信在它修改之前,没有其它线程去修改它.而synchronized是一种悲观锁,它认

非阻塞同步算法与CAS(Compare and Swap)无锁算法

CAS无锁算法 要实现无锁(lock-free)的非阻塞算法有多种实现方法,其中CAS(比较与交换,Compare and swap)是一种有名的无锁算法.CAS, CPU指令,在大多数处理器架构,包括IA32.Space中采用的都是CAS指令,CAS的语义是"我认为V的值应该为A,如果是,那么将V的值更新为B,否则不修改并告诉V的值实际为多少",CAS是项乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起

java总结(基础知识-面试)

l Java发射(案例) l 反射含义: l JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. l JAVA反射(放射)机制:"程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言".从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言.但是JAVA有着一个非常突出的动态相关机制:

构建和实现单点登录解决方案(转载于IBMdeveloperWorks)

将一个开放源码的基于 Java 的身份验证组件集成进 Web 门户中 在现有的应用程序中实现单点登录解决方案(single sign-on,SSO,即登录一次,就可以向所有网络资源验证用户的身份)是非常困难的,但是在构建复杂的门户时,每个开发人员都要面对这个问题.因为门户需要与后端资源集成,而每个后端资源都有自己的身份验证需求,所以门户常常必须向用户提供单点登录特性.在本文中,Chris Dunne 一步步地描述了他为一个 Web 门户构建单点登录解决方案的经历.他将讲解如何设置一个开放源码解决