博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
cas无锁化算法
阅读量:6207 次
发布时间:2019-06-21

本文共 2022 字,大约阅读时间需要 6 分钟。

无锁算法

       CAS, CPU指令,在大多数处理器架构,包括IA32、Space中采用的都是CAS指令,CAS的语义是“我认为V的值应该为A,如果是,那么将V的值更新为B,否则不修改并告诉V的值实际为多少”,CAS是项 乐观锁 技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

      无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步, 所以也叫非阻塞同步(Non-blocking Synchronization)。实现非阻塞同步的方案称为“无锁编程算法”( Non-blocking algorithm)。

      相对应的,独占锁是一种悲观锁,synchronized就是一种独占锁,它假设最坏的情况,并且只有在确保其它线程不会造成干扰的情况下执行,会导致其它所有需要锁的线程挂起, 等待持有锁的线程释放锁。

  • 使用lock实现线程同步有很多缺点:
    • 产生竞争时,线程被阻塞等待,无法做到线程实时响应。
    • dead lock,死锁。
    • live lock。
    • 优先级翻转。
    • 使用不当,造成性能下降。 当然在部分情况下,目前来看,无锁编程并不能替代 lock。

实现级别

非同步阻塞的实现可以分成以下三个级别:

  • wait-free
    • 是最理想的模式,整个操作保证每个线程在有限步骤下完成。
    • 保证系统级吞吐(system-wide throughput)以及无线程饥饿。
    • 截止2011年,没有多少具体的实现。即使实现了,也需要依赖于具体CPU。
  • lock-free
    • 允许个别线程饥饿,但保证系统级吞吐。确保至少有一个线程能够继续执行。
    • wait-free的算法必定也是lock-free的。
  • obstruction-free
    • 在任何时间点,一个线程被隔离为一个事务进行执行(其他线程suspended),并且在有限步骤内完成。
    • 在执行过程中,一旦发现数据被修改(采用时间戳、版本号),则回滚。也叫做乐观锁,即乐观并发控制(OOC)。
    • 事务的过程是:
      • 读取,并写时间戳;
      • 准备写入,版本校验;
      • 校验通过则写入,校验不通过,则回滚。
    • lock-free必定是obstruction-free的。

底层介绍

        java.util.concurrent.atomic中的AtomicXXX,都使用了这些底层的JVM支持为数

字类型的引用类型提供一种高效的CAS操作,而在java.util.concurrent中的大多数类在实现时都直接或间接的使用了这些原子变量类,这些原子变量都调用了 sun.misc.Unsafe 类库里面的 CAS算法,用CPU指令来实现无锁自增.

//JDK源码: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);}复制代码

      因而在大部分情况下,java中使用Atomic包中的incrementAndGet的性能比用synchronized高出几倍。

ABA问题

  • 问题描述       thread1意图对val=1进行操作变成2,cas(val,1,2)。       thread1先读取val=1;thread1被抢占(preempted),让thread2运行。       thread2 修改val=3,又修改回1。       thread1继续执行,发现期望值与“原值”(其实被修改过了)相同,完成CAS操作。

  • 解决方案

    • ABA:添加额外的标记用来指示是否被修改。 从Java1.5开始JDK的atomic包里提供了一个类AtomicStampedReference来解决ABA问题。这个类的compareAndSet方法作用是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。

转载于:https://juejin.im/post/5c0f5bd3f265da615d727d64

你可能感兴趣的文章
《中国人工智能学会通讯》——11.21 结束语
查看>>
自动加密企业关键业务数据 赛门铁克推出全新信息保护解决方案
查看>>
革新以太网交换机架构 全光网络的风刮进园区
查看>>
揭开勒索软件的真面目
查看>>
开源与云计算
查看>>
人工智能时代号角已吹响 COMPUTEX如何凝聚AI这股力量?
查看>>
物联网商机迸发 LPWAN芯片现身 本文转自d1net(转载)
查看>>
站长快讯 WordPress跨站攻击漏洞修补
查看>>
Teradata QueryGrid整合最佳分析技术 拓展客户选择空间
查看>>
《网络空间欺骗:构筑欺骗防御的科学基石》一1.1 主动网络空间防御中网络空间抵赖与欺骗的视图...
查看>>
Hadoop不适合哪些场景 哪些场景适合?
查看>>
欧洲的数据中心与美国的数据中心如何区分?
查看>>
锐捷亮相GITC:请互联网企业为我点个赞!
查看>>
IBM将推NVMe存储解决方案
查看>>
报表系统的雄心
查看>>
如何快速掌握一门新技术/语言/框架
查看>>
企业如何杜绝云端数据泄密?
查看>>
《Drupal实战》——3.3 使用Views创建列表
查看>>
域名服务商GoDaddy第四季度扭亏为盈
查看>>
诺基亚报告称:到2020年北美电子邮件流量占比将跌至7%
查看>>