Java 多线程 - CAS

前言

记录在学习线程安全知识点中,关于CAS的有关知识点。

线程安全是指:多个线程不管以何种方式访问某个类,并且在主调代码中不需要进行同步,都能表现正确的行为。

常见的线程安全实现方法分为不可变对象、线程互斥同步、非阻塞同步、线程本地存储等方案,本文要讲的就是非阻塞同步中的核心CAS.

非阻塞同步

从处理问题的方式上说,互斥同步属于一种悲观的并发策略。

随着硬件指令集的发展,我们可以采用基于冲突检查的乐观并发策略,通俗地说,就是先行操作,如果没有其他线程争用共享数据,那操作就成功了;如果共享数据有争用,产生了冲突,那就再采取其他的补偿措施(最常见的补偿措施就是不断地重试,直到成功为止),这种乐观的并发策略的许多实现偶读不需要把线程挂起,因此这种同步操作称为非阻塞同步。

CAS

乐观锁需要操作和冲突检测这两个步骤具备原子性,这里就不能再使用互斥同步来保证了,只能靠硬件来完成硬件支持的原子性操作最典型的是:比较并交换(Compare-and-Swap,CAS)CAS 指令需要有 3 个操作数,分别是内存地址 V、旧的预期值 A 和新值 B。当执行操作时,只有当 V 的值等于 A,才将 V 的值更新为 B。

各种Atomic开头的原子类,内部都应用到了CAS。就拿AtomicInteger为例。

J.U.C 包里面的原子类 AtomicInteger 的方法调用了 Unsafe 类的 CAS 操作。

image

看看AtomicInteger对象一次自增,CAS起了什么作用,以下代码是 incrementAndGet() 的源码,可以看到内部调用了 Unsafe 对象的 getAndAddInt()

image

以下代码是 getAndAddInt()源码,var1 指示对象内存地址,var2指示该字段相对对象内存地址的偏移,var4 指示操作需要加的数值,这里为 1。通过 getIntVolatile(var1, var2) 得到旧的预期值,通过调用 compareAndSwapInt() 来进行 CAS比较如果该字段内存地址中的值等于var5,那么就更新内存地址为 var1+var2 的变量为 var5+var4

image

compareAndSwapInt(var1, var2, var5, var5 + var4 其实换成compareAndSwapInt(obj, offset, expect, update)比较清楚,意思就是如果obj内的valueexpect相等,就证明没有其他线程改变过这个变量,那么就更新它为update,如果这一步的CAS没有成功,那就采用自旋的方式继续进行CAS操作,取出乍一看这也是两个步骤了啊,其实在JNI里是借助于一个CPU指令完成的。所以还是原子操作。

CAS 的问题

  • ABA问题
    • 描述:如果一个变量初次读取的时候是 A 值,它的值被改成了 B,后来又被改回为 A,那 CAS 操作就会误认为它从来没有被改变过。
    • 解决方案:J.U.C 包提供了一个带有标记的原子引用类 AtomicStampedReference 来解决这个问题,它可以通过控制变量值的版本来保证 CAS 的正确性。大部分情况下 ABA 问题不会影响程序并发的正确性,如果真的需要解决 ABA 问题,改用传统的互斥同步可能会比原子类更高效
  • 循环时间长开销大
    • 自旋CAS(也就是不成功就一直循环执行直到成功)如果长时间不成功,会给CPU带来比较大的执行开销。
  • 只能保证一个共享变量的原子操作
    • CAS 只对单个共享变量有效,当操作涉及跨多个共享变量时CAS 无效。但是从 JDK 1.5开始,提供了AtomicReference类来保证引用对象之间的原子性,你可以把多个变量放在一个对象里来进行 CAS操作.所以我们可以使用锁或者利用AtomicReference类把多个共享变量合并成一个共享变量来操作。

CAS与synchronized的使用情景

  • 简单的来说CAS适用于写比较少的情况下(多读场景,冲突一般较少)
  • synchronized适用于写比较多的情况下(多写场景,冲突一般较多)
  • 对于资源竞争较少(线程冲突较轻)的情况,使用synchronized同步锁进行线程阻塞和唤醒切换以及用户态内核态间的切换操作额外浪费消耗cpu资源;而CAS基于硬件实现,不需要进入内核,不需要切换线程,操作自旋几率较少,因此可以获得更高的性能。
  • 对于资源竞争严重(线程冲突严重)的情况,CAS自旋的概率会比较大,从而浪费更多的CPU资源,效率低于synchronized。

CAS 的应用

使用 CAS 原子指令来处理对数据的并发访问,这是非阻塞算法得以实现的基础。关于非阻塞算法是属于J.U.C中并发容器部分的知识,属于比较难的内容。目前先引用几篇文章。作为记录,之后有机会再详细学习。

  1. 非阻塞算法在并发容器中的实现

  2. 非阻塞同步算法实战(一)

  3. 非阻塞同步算法实战(二)-BoundlessCyclicBarrier

  4. 非阻塞同步算法实战(三)-LatestResultsProvider

参考

  1. 《深入理解Java虚拟机》
  2. https://www.ibm.com/developerworks/cn/java/j-lo-concurrent/
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,843评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,538评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,187评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,264评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,289评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,231评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,116评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,945评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,367评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,581评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,754评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,458评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,068评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,692评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,842评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,797评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,654评论 2 354

推荐阅读更多精彩内容

  • 乐观锁与悲观锁 悲观锁 总是假设最坏的情况,每次获取数据都认为别人会修改,所以拿数据时会上锁,一直到释放锁不允许其...
    CieloSun阅读 477评论 0 0
  • 一、线程状态转换新建(New)可运行(Runnable)阻塞(Blocking)无限期等待(Waiting)限期等...
    达微阅读 581评论 1 2
  • layout: posttitle: 《Java并发编程的艺术》笔记categories: Javaexcerpt...
    xiaogmail阅读 5,817评论 1 19
  • 看了群主的java体系结构 http://cmsblogs.com/wp-content/images/share...
    lijiaccy阅读 776评论 0 0
  • 昨天下午出去买菜,刚走出家门便看见楼道里有疑似狗屎的可疑物,就在楼道进门的中间。回忆两点多时听见遛狗男和他的狗在外...
    疏林红叶阅读 241评论 4 9