首先弄清楚什么是cas:
在计算机科学中,比较和交换(Conmpare And Swap)是用于实现多线程同步的原子指令。 它将内存位置的内容与给定值进行比较,只有在相同的情况下,将该内存位置的内容修改为新的给定值。 这是作为单个原子操作完成的。 原子性保证新值基于最新信息计算; 如果该值在同一时间被另一个线程更新,则写入将失败。 操作结果必须说明是否进行替换; 这可以通过一个简单的布尔响应(这个变体通常称为比较和设置),或通过返回从内存位置读取的值来完成(摘自维基本科)
在jdk后引入了一个很重要的包 java.util.concurrent.atomic
在这个包下很多类比如:AtomicInteger AtomicLong等就是为了多线程操作变量,线看下例子
package thread;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntegerDemo {
public static void main(String[] args) {
//主内存的值
AtomicInteger atomicInteger = new AtomicInteger(5);
boolean isUpdate = atomicInteger.compareAndSet(5,2019);
System.out.println("-->"+atomicInteger.get());
System.out.println("isUpdate-->"+isUpdate);
}
}
首先主内存中的值是5 比如有二个线程t1和t2,那么在t1,t2中的工作内存的值都是从主内存拷贝过去的,也就是说t1,t2中的值都是5 ,那么这个时候t1线程对其进行修改,修改成2019,这个时候t1工作内存就把这个值刷新到主内存,主内存判断这个期望的值和主内存的值一样,那么就修改主内存中的值 为2019
看下源码:
/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
* @param expect the expected value
* @param update the new value
* @return {@code true} if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
我们可以看到
Atomically sets the value to the given updated value if the current value {@code ==} the expected value
这个解释,就是说如果这个当前期望的值和设置的atomic的值相等就更新新的值
大厂都喜欢问底层实现原理,那么如果是面试肯定会问,它是怎么实现的?
package thread;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntegerDemo {
public static void main(String[] args) {
//主内存的值
AtomicInteger atomicInteger = new AtomicInteger(5);
System.out.println("atomicInteger-->"+atomicInteger.getAndIncrement());
}
}
点击getAndIncrement()方法进入到源码中,
/**
* Atomically increments by one the current value.
*
* @return the previous value
*/
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
它三个参数分别是:
this:表示当前类
valueOffset: 内存偏移量(内存地址)
1:就是常量了
发现getAndIncrement()方法是由unsafe对象调用的,而unsafe对象的创建:
private static final Unsafe unsafe = Unsafe.getUnsafe();
进入Unsafe类后是调用了:
public final int getAndAddInt(java.lang.Object o, long l, int i) { /* compiled code */ }
Unsafe是CAS的核心类,由于Java方法无法访问底层系统,需要通过本地(native)方法来访问,Unsafe相当于一个后门,基于该类可以直接操作特定内存的数据,Unsafe类存在与com.misc包下,其内部方法操作可以像C的指针一样操作内存,因为Java中的CAS操作依赖于Unsafe类的方法
CAS的全称是Compare. And. Swap 它是一条CPU并发原语,
CAS并发原语体现在Java语言当中的sun.misc.Unsafe类中的各个方法,调用CAS中的方法,JVM会帮助我们实现CAS的汇编指令,这是一个完整依赖硬件的功能,通过它实现了Java中的原子操作,
CAS缺点:
1:循环时间长,开销大 因为底层使用了do...while操作
2:只能保证一个共享变量的原子操作
3:引出ABA问题?