CAS简介说明

书欣 Java教程 发布时间:2022-07-29 14:19:27 阅读数:17665 1
下文笔者讲述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问题
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaCourse/202207/4069.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者