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:可见性、原子性、有序性。
}

02-CAS-学习笔记其中:
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类中的方法都直接调用操作系统底层资源执行相应任务。

02-CAS-学习笔记
compareAndSwapInt :比较并交换。真实值和期望值相等时,交换成功。

为什么用cas而不用synchronized?

  1. synchronized同一时间段只允许一个线程来访问,一致性得到了保障,但是并发性下降了
  2. 可以反复的通过CAS比较,直到比较成功的那一刻为止,既保证了一致性也提高了并发性

CAS缺点

循环时间长,开销大
getAndAddInt方法里面有个do…while,如果cas(比较并交换)失败的话,就会一直进行尝试。如果cas长时间不成功,那么就可能给cpu带来很大的开销。