写点什么

Java 线程 (十):CAS

发布于: 2021 年 11 月 07 日
  1. public?final?int?incrementAndGet()?{??

  2. ????for?(;;)?{??

  3. ????????int?current?=?get();??

  4. ????????int?next?=?current?+?1;??

  5. ????????if?(compareAndSet(current,?next))??

  6. ????????????return?next;??

  7. ????}??

  8. }??


[java]? view plain copy print ?




  1. public?final?int?decrementAndGet()?{??

  2. ????for?(;;)?{??

  3. ????????int?current?=?get();??

  4. ????????int?next?=?current?-?1;??

  5. ????????if?(compareAndSet(current,?next))??

  6. ????????????return?next;??

  7. ????}??

  8. }??


以这两个方法为例,incrementAndGet 方法相当于原子性的++i,decrementAndGet 方法相当于原子性的--i(根据第一章第二章我们知道++i 或--i 不是一个原子性的操作),这两个方法中都没有使用阻塞式的方式来保证原子性(如 Synchronized),那它们是如何保证原子性的呢,下面引出 CAS。


Compare And Swap


==============================================================================


CAS 指的是现代 CPU 广泛支持的一种对内存中的共享数据进行操作的一种特殊指令。这个指令会对内存中的共享数据做原子的读写操作。简单介绍一下这个指令的操作过程:首先,CPU 会将内存中将要被更改的数据与期望的值做比较。然后,当这两个值相等时,CPU 才会将内存中的数值替换为新的值。否则便不做操作。最后,CPU 会将旧的数值返回。这一系列的操作是原子的。它们虽然看似复杂,但却是 Java 5 并发机制优于原有锁机制的根本。简单来说,CAS 的含义是“我认为原有的值应该是什么,如果是,则将原有的值更新为新值,否则不做修改,并告诉我原来的值是多少”。(这段描述引自《Java 并发编程实践》)


简单的来说,CAS 有 3 个操作数,内存值 V,旧的预期值 A,要修改的新值 B。当且仅当预期值 A 和内存值 V 相同时,将内存值 V 修改为 B,否则返回 V。这是一种乐观锁的思路,它相信在它修改之前,没有其它线程去修改它;而 Synchronized 是一种悲观锁,它认为在它修改之前,一定会有其它线程去修改它,悲观锁效率很低。下面来看一下 AtomicInteger 是如何利用 CAS 实现原子性操作的。


volatile 变量




[java]? view plain copy print ?




  1. private?volatile?int?value;??


首先声明了一个 volatile 变量 value,在 第二章我们知道 volatile 保证了变量的内存可见性,也就是所有工作线程中同一时刻都可以得到一致的值。


[java]? view plain copy print ?




  1. public?final?int?get()?{??

  2. ????return?value;??

  3. }??


Compare And Set




[java]? view plain copy print ?




  1. //?setup?to?use?Unsafe.compare


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


AndSwapInt?for?updates??


  1. private?static?final?Unsafe?unsafe?=?Unsafe.getUnsafe();??

  2. private?static?final?long?valueOffset;//?注意是静态的??

  3. static?{??

  4. ??try?{??

  5. ????valueOffset?=?unsafe.objectFieldOffset??

  6. ????????(AtomicInteger.class.getDeclaredField("value"));//?反射出 value 属性,获取其在内存中的位置??

  7. ??}?catch?(Exception?ex)?{?throw?new?Error(ex);?}??

  8. }??

  9. public?final?boolean?compareAndSet(int?expect,?int?update)?{??

  10. ??return?unsafe.compareAndSwapInt(this,?valueOffset,?expect,?update);??

  11. }??

评论

发布
暂无评论
Java线程(十):CAS