Java CAS 的原子操作实现

Jakcy Java 2021-10-09 23

CAS原理

修改内存中的某一个值V,提供一个旧值A和一个新值B。如果提供的旧值V和A相等就把B写入V。这个过程是原子性的。CAS执行结果要么成功要么失败,对于失败的情形下,采用不断重试直至修改成功或者直接放弃修改。

代码实现

package com.dome.test;

import sun.misc.Unsafe;
import java.lang.reflect.Field;

public class CASCounter {

    private int value=0;
    private static final sun.misc.Unsafe UNSAFE;
    private static final long nextOffset;

    static {
        try {
            UNSAFE = getUnsafe();
            Class<?> k = CASCounter.class;
            // 获取字段相对Java对象的“起始地址”的偏移量
            // 可通过getInt、getLong、getObject之类的方法可以使用前面获取的偏移量来访问对象的字段
            nextOffset = UNSAFE.objectFieldOffset (k.getDeclaredField("value"));
        } catch (Exception e) {
            throw new Error(e);
        }
    }

    private static Unsafe getUnsafe() {
        try {
            return Unsafe.getUnsafe();
        } catch (SecurityException se) {
            try {
                Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
                theUnsafe.setAccessible(true);
                return (Unsafe) theUnsafe.get(Unsafe.class);
            } catch (Exception e) {
                throw new RuntimeException("exception while trying to get Unsafe", e);
            }
        }
    }

    /**
    * 1,基于sun.misc.Unsafe实现
    */
    public boolean compareAndSwapInt1(int oldValue, int newValue) {
        return UNSAFE.compareAndSwapInt(this,nextOffset,oldValue,newValue);

    }

    /**
    * 2,基于同步块实现
    */
    public boolean compareAndSwapInt2(int oldValue, int newValue) {
        synchronized (this) {
            if (value == oldValue) {
                value = newValue;
                return true;
            } else {
                return false;
            }
        }
    }

    public int index() {
        int oldvalue;
        do {
            oldvalue = value;
        } while (!compareAndSwapInt1(oldvalue, oldvalue + 1));
        return oldvalue + 1;
    }

    public int getValue(){
        return UNSAFE.getInt(this,nextOffset);
    }

}