CAS学习

定义
CAS操作包含三个操作数-内存位置(V)、期望值(A)和新值(B)
如果内存位置的值与期望值匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不作任何操作。无论哪种情况,它都会在CAS指令之前返回该位置的值。
(CAS在一些特殊情况下仅返回CAS是否成功,而不提取当前值)CAS有效的说明了
“我认为位置V应该包含值A:如果包含该值,则将B放到这个位置;否则,不要更改该位置的值,只告诉我这个位置现在的值即可。”
写一个简易CAS锁

package concurrent;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class Demo1 {
    static int count = 0;

    public static void main(String[] args) throws InterruptedException {
        long startTime = System.currentTimeMillis();
        int threadSize = 100;
        //保证100个线程之后再执行后边的代码
        CountDownLatch countDownLatch = new CountDownLatch(threadSize);
        for (int i = 0; i < threadSize; i++) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    for (int i = 0; i < 10; i++) {
                        request();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {

                    countDownLatch.countDown();
                }
            }
        });
            thread.start();
        }
        //保证100个线程之后再执行后边的代码
        countDownLatch.await();
        long endTime = System.currentTimeMillis();
        System.out.println(Thread.currentThread().getName()+",耗时:"+(endTime-startTime)+",count="+count);
    }

    public static synchronized boolean compareAndSwap(int expectCount,int newCount){
        if (expectCount==getCount()){
            count = newCount;
            return true;
        }
        return false;
    }

    public static int getCount(){
        return count;
    }

    public  static  void request() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(5);
        //count ++操作实际上是由3步来完成!(jvm执行引擎)
        //1,获取count的值,记做A:A-count
        //2.将A值+1,得到B:B-A+1
        // 3,将B值赋值给count
            //升级第3步的实现:
            //1,获取锁
            //2.获取以Fcount最新的值,记做LV
            //3,判断LV是否等于A,如果相等,则将B的值赋值给count,并返回true,否则返回false
            //4.释放锁
        //count++;   改为如下操作
        int expectCont;
        while (!compareAndSwap(expectCont=getCount(),expectCont+1)){};

    }
}

java中提供了对CAS操作的支持,具体在sun.misc.unsafe类

	//参数var1:表示要操作的对象
	//参数var2:表示要操作对象中属性地址的偏移量
	//参数var4:表示需要修改数据的期望的值
	//参数var5:表示需要修改为的新值
	public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);

    public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

    public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

CAS实现原理

CAS通过调用JNT的代码实现,JNI:java Native Interface,允许java调用其它语言。而compareAndSwapxxx系列的方法就是借助"C语言”来调用cpu底层指令实现的。
以常用的Intel x86平台来说,最终映射到的cpu的指令为"cmpxchg",这是一个原子指令,cpu执行此命令时,实现比较并替换的操作!

现代计算机动不动就上百核心,cmpxchg怎么保证多核心下的线程安全?

系统底层进行CAS操作的时候,会判断当前系统是否为多核心系统,如果是就给“总线”加锁,只有一个线程会对总线加锁成功,加锁成功之后会执行CAS操作,也就是说CAS的原子性是平台级别的!

compareAndSet函数

		//expectedReference:期望引用
		//newReference:新值引用
		//expectedStamp:期望引用的版本号
		//newStamp:新值版本号
public boolean compareAndSet(V   expectedReference,
                                 V   newReference,
                                 int expectedStamp,
                                 int newStamp) {
        Pair<V> current = pair;
        return
        	//期望引用与当前引用一致
            expectedReference == current.reference &&
            //期望版本与当前版本一致
            expectedStamp == current.stamp &&                      
            (
            //如果新的修改引用与当前引用 新的版本与当前版本一致,就不用创建新的Pair对象
            (newReference == current.reference &&
              newStamp == current.stamp)     ||
              //创建新的Pair对象
             casPair(current, Pair.of(newReference, newStamp))
             
			);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值