CAS简介说明
下文笔者讲述CAS简介说明,如下所示
CAS简介
CAS: 其英文缩写为(Compare And Swap),其功能就是比较和交换,是CPU支持的一种内存交换指令 此指令会对内存中共享数据进行操作,它对内存中的共享数据进行原子操作 主要用于先判断新值是否发生变化,不相同则不做更新 主要事项: 1.CAS是一种无锁的实现模式,它是一种乐观锁的实现模式, 它可保证多线程并发中保障共享资源的原子性操作(相对于synchronized或Lock是一种轻量级的实现) 2.jdk中有一些原子类,如: AtomicInteger、CurrentHashMap
AtomicInteger使用说明
未使用AtomicInteger类的原子类实现
public class ThreadSafeTest { public static volatile int i = 0; public synchronized void increase() { i++; } }基于AtomicInteger类的实现
public class ThreadSafeTest { private final AtomicInteger counter = new AtomicInteger(0); public int increase(){ return counter.addAndGet(1); } }
AtomicInteger类简介
AtomicInteger是 java.util.concurrent.atomic包下的一个原子类 该包下还有AtomicBoolean, AtomicLong,AtomicLongArray, AtomicReference等原子类 主要用于在高并发环境下,保证线程安全。
AtomicInteger常用API
AtomicInteger类提供了如下常见的API功能: public final int get():获取当前的值 public final int getAndSet(int newValue):获取当前的值,并设置新的值 public final int getAndIncrement():获取当前的值,并自增 public final int getAndDecrement():获取当前的值,并自减 public final int getAndAdd(int delta):获取当前的值,并加上预期的值 void lazySet(int newValue): 最终会设置成newValue,使用lazySet设置值后,可能导致其他线程在之后的一小段时间内还是可以读到旧的值。
AtomicInteger核心源码
public class AtomicInteger extends Number implements java.io.Serializable { private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; static { try { // 用于获取value字段相对当前对象的“起始地址”的偏移量 valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } private volatile int value; //返回当前值 public final int get() { return value; } //递增加detla public final int getAndAdd(int delta) { // 1、this:当前的实例 // 2、valueOffset:value实例变量的偏移量 // 3、delta:当前value要加上的数(value+delta)。 return unsafe.getAndAddInt(this, valueOffset, delta); } //递增加1 public final int incrementAndGet() { return unsafe.getAndAddInt(this, valueOffset, 1) + 1; } ... }
AtomicInteger底层 通过volatile变量和CAS两者相结合来保证更新数据的原子性
CAS的工作原理
CAS的实现原理: 是由Unsafe类和其中的自旋锁来完成
UnSafe类
sun.misc.Unsafe是JDK内部用的工具类 它通过暴露一些Java意义上说“不安全”的功能给Java层代码 来让JDK能够更多的使用Java代码来实现一些原本是平台相关的 需要使用native语言(C或C++)才可以实现的功能 该类不应该在JDK核心类库之外使用
Unsafe类的功能
Unsafe类的功能: 内存操作、CAS、Class相关、对象操作、数组相关、内存屏障、系统相关、线程调度等功能
Unsafe类常见方法
Unsafe类拥有 objectFieldOffset()方法: 用于获取某个字段相对Java对象的“起始地址”的偏移量 getInt、getLong、getObject等方法: 可以使用前面获取的偏移量来访问某个Java对象的某个字段例:
AtomicInteger中的static代码块 使用objectFieldOffset()方法
Unsafe与CAS
AtomicInteger调用Unsafe#getAndAddInt方法 public final int incrementAndGet() { return unsafe.getAndAddInt(this, valueOffset, 1) + 1; } AtomicInteger调用UnSafe类的CAS方法 JVM实现汇编指令,从而实现原子操作 在Unsafe中getAndAddInt方法实现如下 public final int getAndAddInt(Object var1, long var2, int var4) { int var5; do { var5 = this.getIntVolatile(var1, var2); } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); return var5; } getAndAddInt方法有三个参数: 第一个参数表示当前对象,也就是new的那个AtomicInteger对象; 第二个表示内存地址; 第三个表示自增步伐, 在AtomicInteger#incrementAndGet中默认的自增步伐是1 getAndAddInt方法中 先把当前对象主内存中的值赋给val5 然后进入while循环。判断当前对象此刻主内存中的值是否等于val5 如果是,就自增(交换值),否则继续循环,重新获取val5的值 注意事项: 1.compareAndSwapInt方法,是一个native方法 这个方法汇编之后是CPU原语指令 原语指令是连续执行不会被打断的 所以可以保证原子性 2.getAndAddInt方法中还涉及到一个实现自旋锁 自旋的概念指:getAndAddInt方法中的do while循环操作 当预期值和主内存中的值不等时 就重新获取主内存中的值 3.CAS缺点: 内部使用自旋的方式进行CAS更新( while循环进行CAS更新,如果更新失败,则循环再次重试) 当长时间都不成功的话,就使CPU开销变大 4.Unsafe类还支持其他的CAS方法,如compareAndSwapObject、compareAndSwapInt、compareAndSwapLong
CAS缺点
我们都知道使用CAS可实现原子性操作,但是它还具有以下缺点,如下所示1.长时间未运行完毕,则会产生CPU开销大 2.由于只保证共享变量的原子操作,则会产生ABA问题
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。