02-CAS-学习笔记
CAS(CompareAndSet)比较并交换
package cn.chen.demo.casdemo;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author chenlf
*
* 1.CAS是什么? CompareAndSet 比较并交换
*/
public class CasDemo {
public static void main(String[] args) {
//主物理内存的值:初始值为1。AtomicInteger原子类
AtomicInteger atomicInteger = new AtomicInteger(1);
//主线程:
//1.如果现在主物理内存还是1,那么就将主物理内存的值改成256
// -- 工作内存中修改变量为256,然后写回主物理内存,将主物理内存的共享变量值修改成256.
//2.如果现在主物理内存不是1,那么就无法修改主物理内存的值了
System.out.println(
atomicInteger.compareAndSet(1, 256)
+ "," + atomicInteger.get()
);
System.out.println(
atomicInteger.compareAndSet(1, 1024)
+ "," + atomicInteger.get()
);
}
//JMM:可见性、原子性、有序性。
}
其中:
this :指当前对象,即atomicInteger
valueOffset:当前内存地址
expect:期望值(与主物理内存值做比较,如何期望值与主物理内存相等时则可以做更新修改),即1
update:更新值,即256
CAS底层原理
1.AtomicInteger.getAndIncrement() 【不加synchronized都可以保证i++在多线程情况下的安全问题】
/**
* this:当前对象
* valueOffset:内存地址
* 1 :加1
*/
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
2.Unsafe 【来自于JVM的rt.jar运行jar包里面】
是cas的核心类,由于java方法无法直接访问底层系统,需要通过本地(native)方法来访问,Unsafe相当于一个后门,基于该类可以直接操作特定内存的数据。
Unsafe类存在于sun.misc包中,其内部方法操作可以像C的指针一样直接操作内存,因为java中CAS操作的执行依赖于Unsafe类的方法。
Unsafe类中的所有方法都是native修饰的,也就是说Unsafe类中的方法都直接调用操作系统底层资源执行相应任务。
compareAndSwapInt :比较并交换。真实值和期望值相等时,交换成功。
为什么用cas而不用synchronized?
- synchronized同一时间段只允许一个线程来访问,一致性得到了保障,但是并发性下降了
- 可以反复的通过CAS比较,直到比较成功的那一刻为止,既保证了一致性也提高了并发性
CAS缺点
循环时间长,开销大
getAndAddInt方法里面有个do…while,如果cas(比较并交换)失败的话,就会一直进行尝试。如果cas长时间不成功,那么就可能给cpu带来很大的开销。