[转]CAS原理

在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁(后面的章节还会谈到锁)。

锁机制存在以下问题:

(1)在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题。

(2)一个线程持有锁会导致其它所有需要此锁的线程挂起。

(3)如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能风险。

volatile是不错的机制,但是volatile不能保证原子性。因此对于同步最终还是要回到锁机制上来。

独占锁是一种悲观锁,synchronized就是一种独占锁,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。而另一个更加有效的锁就是乐观锁。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。

CAS 操作

上面的乐观锁用到的机制就是CAS,Compare and Swap。

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

非阻塞算法 (nonblocking algorithms)

一个线程的失败或者挂起不应该影响其他线程的失败或挂起的算法。

现代的CPU提供了特殊的指令,可以自动更新共享数据,而且能够检测到其他线程的干扰,而 compareAndSet() 就用这些代替了锁定。

拿出AtomicInteger来研究在没有锁的情况下是如何做到数据正确性的。

private volatile int value;

首先毫无以为,在没有锁的机制下可能需要借助volatile原语,保证线程间的数据是可见的(共享的)。这样才获取变量的值的时候才能直接读取。

public final int get() {
        return value;
    }

然后来看看++i是怎么做到的。

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

在这里采用了CAS操作,每次从内存中读取数据然后将此数据和+1后的结果进行CAS操作,如果成功就返回结果,否则重试直到成功为止。

而compareAndSet利用JNI来完成CPU指令的操作。

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

整体的过程就是这样子的,利用CPU的CAS指令,同时借助JNI来完成Java的非阻塞算法。其它原子操作都是利用类似的特性完成的。

而整个J.U.C都是建立在CAS之上的,因此对于synchronized阻塞算法,J.U.C在性能上有了很大的提升。

CAS看起来很爽,但是会导致“ABA问题”。

CAS算法实现一个重要前提需要取出内存中某时刻的数据,而在下时刻比较并替换,那么在这个时间差类会导致数据的变化。

比如说一个线程one从内存位置V中取出A,这时候另一个线程two也从内存中取出A,并且two进行了一些操作变成了B,然后two又将V位置的数据变成A,这时候线程one进行CAS操作发现内存中仍然是A,然后one操作成功。尽管线程one的CAS操作成功,但是不代表这个过程就是没有问题的。如果链表的头在变化了两次后恢复了原值,但是不代表链表就没有变化。因此前面提到的原子操作AtomicStampedReference/AtomicMarkableReference就很有用了。这允许一对变化的元素进行原子操作。

[转]CAS原理

时间: 2024-10-06 13:52:40

[转]CAS原理的相关文章

CAS原理与协议

SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. SSO的解决方案很多,比如收费的有UTrust.惠普灵动等,开源的有CAS.Smart SSO等,其中应用最为广泛的是CAS. CAS (Central Authentication Service)中央认证服务.CAS(Central Authentication Service)是一款不错的针对 Web 应用的单点登录框架. CAS 具有以下特点: 开源的企业

Java CAS原理

java.util.concurrent包完全建立在CAS之上的,没有CAS就不会有此包.可见CAS的重要性. CAS CAS:Compare and Swap, 翻译成比较并交换. java.util.concurrent包中借助CAS实现了区别于synchronouse同步锁的一种乐观锁. 本文先从CAS的应用说起,再深入原理解析. CAS应用 CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B.当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做. 非阻塞算法 (n

JAVA CAS原理深度分析(转)

看了一堆文章,终于把JAVA CAS的原理深入分析清楚了. 感谢GOOGLE强大的搜索,借此挖苦下百度,依靠百度什么都学习不到! 参考文档: http://www.blogjava.net/xylz/archive/2010/07/04/325206.html http://blog.hesey.net/2011/09/resolve-aba-by-atomicstampedreference.html http://www.searchsoa.com.cn/showcontent_69238.

JAVA CAS原理深度分析

参考文档: http://www.blogjava.net/xylz/archive/2010/07/04/325206.html http://blog.hesey.net/2011/09/resolve-aba-by-atomicstampedreference.html http://www.searchsoa.com.cn/showcontent_69238.htm http://ifeve.com/atomic-operation/ http://www.infoq.com/cn/ar

转:JAVA CAS原理深度分析

看了一堆文章,终于把Java CAS的原理深入分析清楚了. 感谢GOOGLE强大的搜索,借此挖苦下百度,依靠百度什么都学习不到! 参考文档: http://www.blogjava.net/xylz/archive/2010/07/04/325206.html http://blog.hesey.net/2011/09/resolve-aba-by-atomicstampedreference.html http://www.searchsoa.com.cn/showcontent_69238.

[转]采用CAS原理构建单点登录

采用CAS原理构建单点登录 转载地址:http://www.cnblogs.com/shanyou/archive/2009/08/30/1556659.html 企业的信息化过程是一个循序渐进的过程,在企业各个业务网站逐步建设的过程中,根据各种业务信息水平的需要构建了相应的应用系统,由于这些应用系统一般是在不同的时期开发完成的,各应用系统由于功能侧重.设计方法和开发技术都有所不同,也就形成了各自独立的用户库和用户认证体系.随着新的业务网站不断的增加,用户在每个应用系统中都有独立的账号,这样就造

转-Java CAS原理深度分析

参考文档: http://www.blogjava.net/xylz/archive/2010/07/04/325206.html http://blog.hesey.net/2011/09/resolve-aba-by-atomicstampedreference.html http://www.searchsoa.com.cn/showcontent_69238.htm http://ifeve.com/atomic-operation/ http://www.infoq.com/cn/ar

Java CAS 原理分析

目录 1 简介 2 背景介绍 1.简介 CAS 全称是 compare and swap,是一种用于在多线程环境下实现同步功能的机制.CAS 操作包含三个操作数 – 内存位置.预期数值和新值.CAS 的实现逻辑是将内存位置处的数值与预期数值想比较,若相等,则将内存位置处的值替换为新值.若不相等,则不做任何操作. 在 Java 中,Java 并没有直接实现 CAS,CAS 相关的实现是通过 C++ 内联汇编的形式实现的.Java 代码需通过 JNI 才能调用.关于实现上的细节,我将会在第3章进行分

自实现CAS原理JAVA版,模拟下单库存扣减

在做电商系统时,库存是一个非常严格的数据,根据CAS(check and swap)原来下面对库存扣减提供两种方法,一种是redis,一种用java实现CAS. 第一种 redis实现: 以下这个类是工具类,稍作修改就可运行 import java.util.regex.Pattern; import org.slf4j.Logger;import org.springframework.beans.factory.support.BeanDefinitionReader;import org.