zoukankan      html  css  js  c++  java
  • CAS简介

    概念

    CAS(Compare And Swap 比较并交换),是 乐观锁 的一种典型实现机制。

     

    乐观锁主要的两个步骤:冲突检测、数据更新。

    当多个线程尝试使用CAS同时更新通过一个变量的时候,只有一个线程可以更新变量的值,其他线程都会失败,失败的线程不会被挂起,而是告知失败并可以再次尝试。

     

    CAS操作包括3个操作数:需要读写的内存位置(V)、预期原值(A)、新值(B)。

    如果内存位置与预期原值的A匹配,那么内存位置会更新为新值B;

    如果内存位置与预期原值的值不匹配,那么处理器不会做任何操作;

    无论何种情况,它都会在CAS指令之前返回该位置的值。

     

    缺陷

    1.ABA问题

    现有一个单向链表实现的堆栈,栈顶为A,A.next为B

     线程one希望通过CAS将栈顶A替换为B:head.compareAndSet(A, B); 执行此命令前,线程two介入,将A,B出栈,然后push D、C、A,此时栈结构如下:

     对象B此时处于游离状态,轮到线程one执行CAS操作,检测发现栈顶仍为A,所以CAS成功,栈顶变成B,但是实际上B.next 是null,所以这时的情况为:

       

    解决方法:而B成为了只有1个元素的堆栈,C和D组成的链表就不再存在于此堆栈中,也就是被丢掉了。

    jdk 1.5开始atomic包提供了类AtomicStampedReference来解决ABA问题。

    AtomicStampedReference的compareAndSet方法首先就检测当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子的方式将该引用和该标志的值设置给指定的更新值。

     

    2.循环时间长开销大

    自旋CAS(不成功,就一直循环执行,直至成功)如果长时间不成功,会给CPU带来极大的开销。

     

    3.只能保证一个共享变量的原子操作

    当只对1个变量执行操作时,可以使用循环CAS的方式保证原子操作,但是多个共享变量操作时,循环CAS就无法保证操作的原子性。

    解决方法可以使用锁,但也有一个取巧的方法,就是多个共享变量合并成1个共享变量操作。

     

  • 相关阅读:
    sprintf_s的使用
    DHCP的若干原理解释
    常用在线转换工具
    spring事务隔离级别
    Spring3声明式事务处理事务无法回滚rollback分析(annotation与xml配置混用)
    SQL按时间段统计(5分钟统计一次访问量为例,oracle统计)
    java对象传递小解析
    java、javac -version不一致(java编译及运行环境不一致)的环境变量设置问题解决
    ibator自动代码生成
    Velocity中加载vm文件的三种方式
  • 原文地址:https://www.cnblogs.com/kzyuan/p/14447606.html
Copyright © 2011-2022 走看看