CAS原理分析

原创 2014年02月26日 14:03:07

一、锁机制


常用的锁机制有两种:

1、悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。悲观锁的实现,往往依靠底层提供的锁机制;悲观锁会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。

2、乐观锁:假设不会发生并发冲突,每次不加锁而是假设没有冲突而去完成某项操作,只在提交操作时检查是否违反数据完整性。如果因为冲突失败就重试,直到成功为止。乐观锁大多是基于数据版本记录机制实现。为数据增加一个版本标识,比如在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。 

乐观锁的缺点是不能解决脏读的问题。

在实际生产环境里边,如果并发量不大且不允许脏读,可以使用悲观锁解决并发问题;但如果系统的并发非常大的话,悲观锁定会带来非常大的性能问题,所以我们就要选择乐观锁定的方法.

锁机制存在以下问题:

(1)在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题。
(2)一个线程持有锁会导致其它所有需要此锁的线程挂起。
(3)如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能风险。


二、CAS 操作


JDK 5之前Java语言是靠synchronized关键字保证同步的,这是一种独占锁,也是是悲观锁。java.util.concurrent(J.U.C)种提供的atomic包中的类,使用的是乐观锁,用到的机制就是CAS,CAS(Compare and Swap)有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

现代的CPU提供了特殊的指令,允许算法执行读-修改-写操作,而无需害怕其他线程同时修改变量,因为如果其他线程修改变量,那么CAS会检测它(并失败),算法可以对该操作重新计算。而 compareAndSet() 就用这些代替了锁定。

以AtomicInteger为例,研究在没有锁的情况下是如何做到数据正确性的。

public class AtomicInteger extends Number implements java.io.Serializable {
    
    private volatile int value;


    
    public final int get() {
        return value;
    }
	
	public final int getAndIncrement() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return current;
        }
    }
    
    public final boolean compareAndSet(int expect, int update) {
		return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }


字段value需要借助volatile原语,保证线程间的数据是可见的(共享的)。这样在获取变量的值的时候才能直接读取。然后来看看++i是怎么做到的。getAndIncrement采用了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问题”。
aba实际上是乐观锁无法解决脏数据读取的一种体现。CAS算法实现一个重要前提需要取出内存中某时刻的数据,而在下时刻比较并替换,那么在这个时间差类会导致数据的变化。比如说一个线程one从内存位置V中取出A,这时候另一个线程two也从内存中取出A,并且two进行了一些操作变成了B,然后two又将V位置的数据变成A,这时候线程one进行CAS操作发现内存中仍然是A,然后one操作成功。尽管线程one的CAS操作成功,但是不代表这个过程就是没有问题的。如果链表的头在变化了两次后恢复了原值,但是不代表链表就没有变化。因此AtomicStampedReference/AtomicMarkableReference就很有用了。


AtomicMarkableReference 类描述的一个<Object,Boolean>的对,可以原子的修改Object或者Boolean的值,这种数据结构在一些缓存或者状态描述中比较有用。这种结构在单个或者同时修改Object/Boolean的时候能够有效的提高吞吐量。 


AtomicStampedReference 类维护带有整数“标志”的对象引用,可以用原子方式对其进行更新。对比AtomicMarkableReference 类的<Object,Boolean>,AtomicStampedReference 维护的是一种类似<Object,int>的数据结构,其实就是对对象(引用)的一个并发计数(标记版本戳stamp)。但是与AtomicInteger 不同的是,此数据结构可以携带一个对象引用(Object),并且能够对此对象和计数同时进行原子操作。


                    
版权声明:本文为博主原创文章,未经博主允许不得转载。

JAVA CAS原理深度分析

看了一堆文章,终于把JAVA CAS的原理深入分析清楚了。 感谢GOOGLE强大的搜索,借此挖苦下百度,依靠百度什么都学习不到!   参考文档: http://www.blogjava.net...
  • Hsuxu
  • Hsuxu
  • 2013年07月25日 13:07
  • 116082

【JAVA笔记——道】并发编程CAS算法

CAS (Compare And Swap) 原子操作实现多线程同步 需要传入1.目标指针reg;2.被比较值oldval;3.更新值newval 执行过程如下Created with Raph...
  • wang135139
  • wang135139
  • 2015年12月26日 19:41
  • 1641

CAS+SSO原理浅谈 - 很详细

SSO 是一个非常大的主题,我对这个主题有着深深的感受,自从广州 UserGroup 的论坛成立以来,无数网友都在尝试使用开源的 CAS , Kerberos 也提供另外一种方式的 SSO ,...
  • ynwso
  • ynwso
  • 2015年08月06日 17:05
  • 1456

Java CAS原理深度分析

  • 2017年07月12日 14:35
  • 194KB
  • 下载

无锁算法——CAS原理

一、无锁算法CAS(比较与交换,Compare and swap) 是一种有名的无锁算法。无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非...
  • Roy_70
  • Roy_70
  • 2017年04月09日 09:32
  • 1643

CAS(compareAndSet)算法及简单应用AtomicInteger

参照链接:http://www.blogjava.net/syniii/archive/2010/11/18/338387.html?opt=admincas算法应用的场合:AsyncTask中为Th...
  • xiaoxiaosunzhao
  • xiaoxiaosunzhao
  • 2011年05月19日 21:20
  • 8328

CAS工作原理

上一节我们说了CAS的一些基本知识,这一节我们说说CAS的工作原理以及一些在Tomcat上CAS-server的配置。         老师经常说一张图胜过千言万语,在学Cas的理论的时候也同时是一张...
  • wangdan199112
  • wangdan199112
  • 2015年05月29日 00:24
  • 1662

Java CAS原理深度分析

  • 2017年07月12日 14:35
  • 194KB
  • 下载

理解CAS算法在JAVA中的作用

http://www.cnblogs.com/onlywujun/articles/3529572.html 在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁...
  • bluetjs
  • bluetjs
  • 2016年08月20日 14:58
  • 682

CAS乐观锁算法

http://www.tuicool.com/articles/zuui6z http://my.oschina.net/u/141149/blog/278748?p=1 CAS无锁算法 要实现无锁...
  • lqglqglqg
  • lqglqglqg
  • 2015年08月19日 17:18
  • 306
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:CAS原理分析
举报原因:
原因补充:

(最多只允许输入30个字)