Java_UnSafe&LockSupport&Atomic

sun.misc.Unsafe 使Java拥有了像C语言的指针一样操作内存空间的能力,一旦能够直接操作内存

Unsafe类使Java拥有了像C语言的指针一样操作内存空间的能力,一旦能够直接操作内存,这也就意味着。 (1)不受jvm管理,也就意味着无法被GC,需要我们手动GC,稍有不慎就会出现内存泄漏。
(2)Unsafe的不少方法中必须提供原始地址(内存地址)和被替换对象的地址,偏移量要自己计算,一旦出现问题就是JVM崩溃级别的异常,会导致整个JVM实例崩溃,表现为应用程序直接crash掉。
(3)直接操作内存,也意味着其速度更快,在高并发的条件之下能够很好地提高效率。
因此,从上面三个角度来看,虽然在一定程度上提升了效率但是也带来了指针的不安全性。

使用方法

获取 Unsafe 实例

sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();

或者也可以使用反射或者Spring提供的UnsafeUtils工具类(如下图)获取到Unsafe实例

如何具体使用

普通读写

Unsafe 可以 读写 一个类的非static属性,即使这个属性是私有的。

public native int getInt(Object var1, long var2);

public native void putInt(Object var1, long var2, int var4);

...
volatile 读写

普通读写无法保证 可见性和有效性,而 volatile 就可以保证 可见性和有效性,但是 相对于 普通读写 更加 昂贵。

public native Object getObjectVolatile(Object var1, long var2);

public native void putObjectVolatile(Object var1, long var2, Object var4);

...
有序写入

有序写入 只保证有序性、不保证可见性,就是 一个线程写入不保证其它线程立即可见。
与 volatile 写入相比,有序写入 代价 相对较小。putOrderedXX写入不保证可见性,但是保证有序性,所谓有序性,就是保证指令不会重排序。

public native void putOrderedObject(Object var1, long var2, Object var4);

public native void putOrderedInt(Object var1, long var2, int var4);

public native void putOrderedLong(Object var1, long var2, long var4);
内存管理(直接操作内存)
//内存管理和操作
public native long allocateMemory(long var1);	//申请内存

public native long reallocateMemory(long var1, long var3);	//调整内存

public native void setMemory(Object var1, long var2, long var4, byte var6);

public void setMemory(long var1, long var3, byte var5) {	//将给定内存块中的所有字节设置为固定值(通常是0)。
    this.setMemory((Object)null, var1, var3, var5);
}

public native void copyMemory(Object var1, long var2, Object var4, long var5, long var7);	//内存复制 可以实现 对象浅拷贝

public void copyMemory(long var1, long var3, long var5) {	//内存复制
    this.copyMemory((Object)null, var1, (Object)null, var3, var5);
}

public native void freeMemory(long var1);	//释放内存
CAS 操作

CAS操作为java的锁机制提供一种新的方案,比如 AtomicInteger等类都是通过该方法实现的。compareAndSwap*方法是原子的,可以避免繁重的锁机制,提高代码效率。
CAS 还广泛应用于 乐观锁 比如 ReentrantLock、ConcurrentHashMap,ConcurrentLinkedQueue等都有用到CAS来实现乐观锁。

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);
偏移量

Unsafe 还提供了获取 对象的指针,通过对 指针进行 偏移,不仅可以修改 指针指向的的数据(即使它们是私有的),甚至可以
找到JVM已经认定为 垃圾、可以进行回收的对象。

public native long staticFieldOffset(Field var1);	//获取静态属性Field在对象中的偏移量,读写静态属性时必须获取其偏移量

public native long objectFieldOffset(Field var1);	//获取非静态属性Field在对象实例中的偏移量,读写对象的非静态属性时会用到这个偏移量

public native Object staticFieldBase(Field var1);	//返回Field所在的对象
...
线程调度

通过park方法将线程进行挂起, 线程将一直阻塞到超时或中断条件出现。unpark方法可以终止一个挂起的线程,使其恢复正常。
整个并发框架中对线程的挂起操作被封装在LockSupport类中,LockSupport类中有各种版本park方法,但最终都调用了Unsafe.park()方法。

public native void unpark(Object var1);				//唤醒线程

public native void park(boolean var1, long var2);	//挂起线程 ;park(false,0) 表示永不到期,一直挂起,直至被唤醒
//park的参数,表示挂起的到期时间,第一个如果是true,表示绝对时间,则var2为绝对时间值,单位是毫秒。第一个参数如果是false,表示相对时间,则var2为相对时间值,单位是纳秒。
类加载 及 非常规对象实例化

可以 动态地创建类、动态的创建一个匿名内部类、判断是否需要初始化一个类、 保证已经初始化过一个类;

public native boolean shouldBeInitialized(Class var1);	//判断是否需要初始化一个类

public native void ensureClassInitialized(Class var1);	//保证已经初始化过一个类

public native Class defineClass(String var1, byte[] var2, int var3, int var4, ClassLoader var5, ProtectionDomain var6);	//方法定义一个类,用于动态地创建类

public native Class defineAnonymousClass(Class var1, byte[] var2, Object[] var3);	//动态的创建一个匿名内部类

通常,我们通过new或反射来实例化对象,而Unsafe类提供的allocateInstance方法,可以直接生成对象实例,且无需调用构造方法和其他初始化方法;这在对象反序列化的时候会很有用,能够重建和设置final字段,而不需要调用构造方法。

public native Object allocateInstance(Class var1) throws InstantiationException;		//实例化一个 类实例 (非常规对象实例化)
内存屏障
public native void loadFence();		//保证在这个屏障之前的所有读操作都已经完成

public native void storeFence();	//保证在这个屏障之前的所有写操作都已经完成

public native void fullFence();		//保证在这个屏障之前的所有读写操作都已经完成
数组操作

arrayBaseOffset(获取数组第一个元素的偏移地址)与arrayIndexScale(获取数组中元素的增量地址)配合起来使用,
就可以定位数组中每个元素在内存中的位置。

由于Java的数组最大值为Integer.MAX_VALUE,使用Unsafe类的内存分配方法可以实现超大数组。实际上这样的数据就可以认为是C数组,因此需要注意在合适的时间释放内存。

//获取 数组 base 内存地址
public native int arrayBaseOffset(Class var1);
//返回 数组中元素与元素之间的偏移地址的增量
public native int arrayIndexScale(Class var1);
系统相关
//获取 本地指针的大小(单位是byte),通常值为4或者8。常量ADDRESS_SIZE就是调用此方法。
public native int addressSize();

public native int pageSize();	内存页的大小,此值为2的幂次方。

源码解读 java8

package sun.misc;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.ProtectionDomain;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;

public final class Unsafe {
	private static final Unsafe theUnsafe;					//单例 对象
    public static final int INVALID_FIELD_OFFSET = -1;
    public static final int ARRAY_BOOLEAN_BASE_OFFSET;
    public static final int ARRAY_BYTE_BASE_OFFSET;
    public static final int ARRAY_SHORT_BASE_OFFSET;
    public static final int ARRAY_CHAR_BASE_OFFSET;
    public static final int ARRAY_INT_BASE_OFFSET;
    public static final int ARRAY_LONG_BASE_OFFSET;
    public static final int ARRAY_FLOAT_BASE_OFFSET;
    public static final int ARRAY_DOUBLE_BASE_OFFSET;
    public static final int ARRAY_OBJECT_BASE_OFFSET;
    public static final int ARRAY_BOOLEAN_INDEX_SCALE;
    public static final int ARRAY_BYTE_INDEX_SCALE;
    public static final int ARRAY_SHORT_INDEX_SCALE;
    public static final int ARRAY_CHAR_INDEX_SCALE;
    public static final int ARRAY_INT_INDEX_SCALE;
    public static final int ARRAY_LONG_INDEX_SCALE;
    public static final int ARRAY_FLOAT_INDEX_SCALE;
    public static final int ARRAY_DOUBLE_INDEX_SCALE;
    public static final int ARRAY_OBJECT_INDEX_SCALE;
    public static final int ADDRESS_SIZE;

    //私有的构造方法
    private Unsafe() {
    }

    private static native void registerNatives();		//注册natives 方法,使得 Unsafe 类 可以操作 C 语言

    static {
        registerNatives();
        Reflection.registerMethodsToFilter(Unsafe.class, new String[]{"getUnsafe"});	//给 Unsafe 注册 getUnsafe 方法
        theUnsafe = new Unsafe();	//实例化 theUnsafe 对象
        ARRAY_BOOLEAN_BASE_OFFSET = theUnsafe.arrayBaseOffset(boolean[].class);
        ARRAY_BYTE_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);
        ARRAY_SHORT_BASE_OFFSET = theUnsafe.arrayBaseOffset(short[].class);
        ARRAY_CHAR_BASE_OFFSET = theUnsafe.arrayBaseOffset(char[].class);
        ARRAY_INT_BASE_OFFSET = theUnsafe.arrayBaseOffset(int[].class);
        ARRAY_LONG_BASE_OFFSET = theUnsafe.arrayBaseOffset(long[].class);
        ARRAY_FLOAT_BASE_OFFSET = theUnsafe.arrayBaseOffset(float[].class);
        ARRAY_DOUBLE_BASE_OFFSET = theUnsafe.arrayBaseOffset(double[].class);
        ARRAY_OBJECT_BASE_OFFSET = theUnsafe.arrayBaseOffset(Object[].class);
        ARRAY_BOOLEAN_INDEX_SCALE = theUnsafe.arrayIndexScale(boolean[].class);
        ARRAY_BYTE_INDEX_SCALE = theUnsafe.arrayIndexScale(byte[].class);
        ARRAY_SHORT_INDEX_SCALE = theUnsafe.arrayIndexScale(short[].class);
        ARRAY_CHAR_INDEX_SCALE = theUnsafe.arrayIndexScale(char[].class);
        ARRAY_INT_INDEX_SCALE = theUnsafe.arrayIndexScale(int[].class);
        ARRAY_LONG_INDEX_SCALE = theUnsafe.arrayIndexScale(long[].class);
        ARRAY_FLOAT_INDEX_SCALE = theUnsafe.arrayIndexScale(float[].class);
        ARRAY_DOUBLE_INDEX_SCALE = theUnsafe.arrayIndexScale(double[].class);
        ARRAY_OBJECT_INDEX_SCALE = theUnsafe.arrayIndexScale(Object[].class);
        ADDRESS_SIZE = theUnsafe.addressSize();
    }

    

    //获取 unsafe 实例,只有由主类加载器加载的类才能调用这个方法
    @CallerSensitive
    public static Unsafe getUnsafe() {
        Class var0 = Reflection.getCallerClass();
        if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
            throw new SecurityException("Unsafe");
        } else {
            return theUnsafe;
        }
    }

    //数组操作
	//获取 数组 base 内存地址
    public native int arrayBaseOffset(Class var1);
    //返回 数组中元素与元素之间的偏移地址的增量
    public native int arrayIndexScale(Class var1);
    

    //对象属性 读写 的操作方法
    public native int getInt(Object var1, long var2);

    public native void putInt(Object var1, long var2, int var4);

    public native Object getObject(Object var1, long var2);

    public native void putObject(Object var1, long var2, Object var4);

    public native boolean getBoolean(Object var1, long var2);

    public native void putBoolean(Object var1, long var2, boolean var4);

    public native byte getByte(Object var1, long var2);

    public native void putByte(Object var1, long var2, byte var4);

    public native short getShort(Object var1, long var2);

    public native void putShort(Object var1, long var2, short var4);

    public native char getChar(Object var1, long var2);

    public native void putChar(Object var1, long var2, char var4);

    public native long getLong(Object var1, long var2);

    public native void putLong(Object var1, long var2, long var4);

    public native float getFloat(Object var1, long var2);

    public native void putFloat(Object var1, long var2, float var4);

    public native double getDouble(Object var1, long var2);

    public native void putDouble(Object var1, long var2, double var4);



    // volatile 对象属性 读写 的操作方法
    public native Object getObjectVolatile(Object var1, long var2);

    public native void putObjectVolatile(Object var1, long var2, Object var4);

    public native int getIntVolatile(Object var1, long var2);

    public native void putIntVolatile(Object var1, long var2, int var4);

    public native boolean getBooleanVolatile(Object var1, long var2);

    public native void putBooleanVolatile(Object var1, long var2, boolean var4);

    public native byte getByteVolatile(Object var1, long var2);

    public native void putByteVolatile(Object var1, long var2, byte var4);

    public native short getShortVolatile(Object var1, long var2);

    public native void putShortVolatile(Object var1, long var2, short var4);

    public native char getCharVolatile(Object var1, long var2);

    public native void putCharVolatile(Object var1, long var2, char var4);

    public native long getLongVolatile(Object var1, long var2);

    public native void putLongVolatile(Object var1, long var2, long var4);

    public native float getFloatVolatile(Object var1, long var2);

    public native void putFloatVolatile(Object var1, long var2, float var4);

    public native double getDoubleVolatile(Object var1, long var2);

    public native void putDoubleVolatile(Object var1, long var2, double var4);


    //对象属性 有序写入 的操作方法
    public native void putOrderedObject(Object var1, long var2, Object var4);

    public native void putOrderedInt(Object var1, long var2, int var4);

    public native void putOrderedLong(Object var1, long var2, long var4);


    //内存管理和操作
    public native long allocateMemory(long var1);	//申请内存

    public native long reallocateMemory(long var1, long var3);	//调整内存

    public native void setMemory(Object var1, long var2, long var4, byte var6);

    public void setMemory(long var1, long var3, byte var5) {	//将给定内存块中的所有字节设置为固定值(通常是0)。
        this.setMemory((Object)null, var1, var3, var5);
    }

    public native void copyMemory(Object var1, long var2, Object var4, long var5, long var7);	//内存复制

    public void copyMemory(long var1, long var3, long var5) {	内存复制
        this.copyMemory((Object)null, var1, (Object)null, var3, var5);
    }

    public native void freeMemory(long var1);	//释放内存


    //cas 操作
    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);


    // 偏移量 操作 方法
     /** @deprecated */
    @Deprecated
    public int fieldOffset(Field var1) {
        return Modifier.isStatic(var1.getModifiers()) ? (int)this.staticFieldOffset(var1) : (int)this.objectFieldOffset(var1);
    }

    /** @deprecated */
    @Deprecated
    public Object staticFieldBase(Class var1) {
        Field[] var2 = var1.getDeclaredFields();

        for(int var3 = 0; var3 < var2.length; ++var3) {
            if (Modifier.isStatic(var2[var3].getModifiers())) {
                return this.staticFieldBase(var2[var3]);
            }
        }

        return null;
    }

    public native long staticFieldOffset(Field var1);	//获取静态属性Field在对象中的偏移量,读写静态属性时必须获取其偏移量

    public native long objectFieldOffset(Field var1);	//获取非静态属性Field在对象实例中的偏移量,读写对象的非静态属性时会用到这个偏移量

    public native Object staticFieldBase(Field var1);	//返回Field所在的对象


    // 线程调度
    public native void unpark(Object var1);				//唤醒线程

    public native void park(boolean var1, long var2);	//挂起线程 ;park(false,0) 表示永不到期,一直挂起,直至被唤醒
    //park的参数,表示挂起的到期时间,第一个如果是true,表示绝对时间,则var2为绝对时间值,单位是毫秒。第一个参数如果是false,表示相对时间,则var2为相对时间值,单位是纳秒。


    //类加载 
    public native boolean shouldBeInitialized(Class var1);	//判断是否需要初始化一个类

    public native void ensureClassInitialized(Class var1);	//保证已经初始化过一个类

    public native Class defineClass(String var1, byte[] var2, int var3, int var4, ClassLoader var5, ProtectionDomain var6);	//方法定义一个类,用于动态地创建类

    public native Class defineAnonymousClass(Class var1, byte[] var2, Object[] var3);	//动态的创建一个匿名内部类

    public native Object allocateInstance(Class var1) throws InstantiationException;		//实例化一个 类实例 (非常规对象实例化)



    //内存屏障
    public native void loadFence();		//保证在这个屏障之前的所有读操作都已经完成

    public native void storeFence();	//保证在这个屏障之前的所有写操作都已经完成

    public native void fullFence();		//保证在这个屏障之前的所有读写操作都已经完成


    //两个系统相关的方法:
    //获取 本地指针的大小(单位是byte),通常值为4或者8。常量ADDRESS_SIZE就是调用此方法。
    public native int addressSize();

    public native int pageSize();	内存页的大小,此值为2的幂次方。



    //采集系统 负载数据
    public native int getLoadAverage(double[] var1, int var2);


    // Atomic 类实现相关
    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }

    public final long getAndAddLong(Object var1, long var2, long var4) {
        long var6;
        do {
            var6 = this.getLongVolatile(var1, var2);
        } while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));

        return var6;
    }

    public final int getAndSetInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var4));

        return var5;
    }

    public final long getAndSetLong(Object var1, long var2, long var4) {
        long var6;
        do {
            var6 = this.getLongVolatile(var1, var2);
        } while(!this.compareAndSwapLong(var1, var2, var6, var4));

        return var6;
    }

    public final Object getAndSetObject(Object var1, long var2, Object var4) {
        Object var5;
        do {
            var5 = this.getObjectVolatile(var1, var2);
        } while(!this.compareAndSwapObject(var1, var2, var5, var4));

        return var5;
    }

}

LockSupport

使用例子

LockSupport.park()								//挂起线程;表示永不到期,一直挂起,直至被其它线程唤醒
LockSupport.park(blocker)						//被 blocker 挂起线程;表示永不到期,一直挂起,直至被其它线程唤醒
LockSupport.unpark(thread)						//唤醒 thread 
LockSupport.parkUntil(blocker, long deadline)	//被 blocker 挂起直到 deadline 时间戳,后 自动唤醒
LockSupport.parkUntil(long deadline)			//挂起直到 deadline 时间戳,后 自动唤醒
LockSupport.parkNanos(blocker, long nanos)		//被 blocker 挂起直到 nanos 毫秒,后 自动唤醒
LockSupport.parkNanos(long nanos)				//挂起直到 nanos 毫秒,后 自动唤醒

源码阅读

基本的线程锁

package java.util.concurrent.locks;
import sun.misc.Unsafe;
public class LockSupport {
	private LockSupport() {}	//私有的构造方法,不能被外部实例化

	private static final sun.misc.Unsafe UNSAFE;	
    private static final long parkBlockerOffset;	//Thread class parkBlocker 字段 内存地址;用于记录线程被谁阻塞的,用于线程监控和分析工具来定位原因的
    private static final long SEED;					//Thread class threadLocalRandomSeed 字段 内存地址
    private static final long PROBE;				//Thread class threadLocalRandomProbe 字段 内存地址
    private static final long SECONDARY;			//Thread class threadLocalRandomSecondarySeed 字段 内存地址
    static {
        try {
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            Class tk = Thread.class;
            parkBlockerOffset = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("parkBlocker"));	//获取 Thread class parkBlocker 字段 内存地址
            SEED = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomSeed"));	//获取 Thread class threadLocalRandomSeed 字段 内存地址
            PROBE = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomProbe"));	//获取 Thread class threadLocalRandomProbe 字段 内存地址
            SECONDARY = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomSecondarySeed"));	//获取 Thread class threadLocalRandomSecondarySeed 字段 内存地址
        } catch (Exception ex) { throw new Error(ex); }
    }

    // 设置 线程t parkBlocker 字段为 arg ;这里只是记录 线程是被谁 阻塞的
    private static void setBlocker(Thread t, Object arg) {
        // Even though volatile, hotspot doesn't need a write barrier here.
        UNSAFE.putObject(t, parkBlockerOffset, arg);
    }

    // 唤醒 thread 线程
    public static void unpark(Thread thread) {
        if (thread != null)
            UNSAFE.unpark(thread);
    }

    // 记录被阻塞者,并一直阻塞 本线程, 清除 被阻塞者信息
    public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);	//设置这个线程 被谁阻塞
        UNSAFE.park(false, 0L);	//一直阻塞这个线程
        setBlocker(t, null);	//设置这个线程 被阻塞者是 null;即清楚 被阻塞者
    }

    //记录被阻塞者,并阻塞 本线程 nanos 毫秒, 清除 被阻塞者信息
    public static void parkNanos(Object blocker, long nanos) {
        if (nanos > 0) {
            Thread t = Thread.currentThread();
            setBlocker(t, blocker);
            UNSAFE.park(false, nanos);
            setBlocker(t, null);
        }
    }	

    //记录被阻塞者,并阻塞 本线程 直到 deadline时间戳, 清除 被阻塞者信息
    public static void parkUntil(Object blocker, long deadline) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(true, deadline);
        setBlocker(t, null);
    }

    //或者 thread 被谁阻塞
    public static Object getBlocker(Thread t) {
        if (t == null)
            throw new NullPointerException();
        return UNSAFE.getObjectVolatile(t, parkBlockerOffset);
    }

    //一直阻塞 本线程
    public static void park() {
        UNSAFE.park(false, 0L);
    }

    //阻塞 本线程 nanos 毫秒
    public static void parkNanos(long nanos) {
        if (nanos > 0)
            UNSAFE.park(false, nanos);
    }

    //阻塞本线程,直到 deadline 时间戳
    public static void parkUntil(long deadline) {
        UNSAFE.park(true, deadline);
    }


    //产生本线程的 SecondarySeed 随机数 种子;为下一次生成随机数的因子
    static final int nextSecondarySeed() {
        int r;
        Thread t = Thread.currentThread();
        if ((r = UNSAFE.getInt(t, SECONDARY)) != 0) {
            r ^= r << 13;   // xorshift
            r ^= r >>> 17;
            r ^= r << 5;
        }
        else if ((r = java.util.concurrent.ThreadLocalRandom.current().nextInt()) == 0)
            r = 1; // avoid zero
        UNSAFE.putInt(t, SECONDARY, r);
        return r;
    }
}

Atomic

基本类型

AtomicBoolean

AtomicInteger

package java.util.concurrent.atomic;
import java.util.function.IntUnaryOperator;
import java.util.function.IntBinaryOperator;
import sun.misc.Unsafe;

public class AtomicInteger extends Number implements java.io.Serializable {
	private static final Unsafe unsafe = Unsafe.getUnsafe();	//获取 unsafe 实例
	private volatile int value;									//注意 需要用 volatile 修饰;有序性和可见性
	private static final long valueOffset;						// 上面 value 在 内部布局中的 内存偏移量;用于原子操作
	static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));	//设置 value 在 内部布局中的 内存偏移量
        } catch (Exception ex) { throw new Error(ex); }
    }
    //无参构造方法
    public AtomicInteger() {
    }
    //有初始值构造方法
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }
    //设置 value 值
    public final void set(int newValue) {
        value = newValue;
    }
    //获取 当前 value 值
    public final int get() {
        return value;
    }

    //有序性 设置 value 值
    public final void lazySet(int newValue) {
        unsafe.putOrderedInt(this, valueOffset, newValue);
    }
    //原子性 设置新值,返回 旧值
    public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
    }
    //原子性 当 value是 expect时,设置为 update
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
    //原子性 + 1 操作,返回旧值
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }
    //原子性 -1 操作,返回旧值
    public final int getAndDecrement() {
        return unsafe.getAndAddInt(this, valueOffset, -1);
    }
    //原子性 +delta 操作,返回旧值
    public final int getAndAdd(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta);
    }
    //原子性 + 1 操作,返回 新值
    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }
    //原子性 -1 操作,返回 新值
    public final int decrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
    }
    //原子性 +delta 操作,返回 新值
    public final int addAndGet(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
    }
    //原子性 使用 updateFunction 值 更新 value 当前值,返回 更新前的值 ;需要注意的是,提供的方法应该无副作用(side-effect-free),即两次执行结果相同,原因是如果由于线程争用导致更新失败会尝试再次执行该方法。
    public final int getAndUpdate(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return prev;
    }
    //原子性 使用 updateFunction 值 更新 value 当前值,返回 更新后的值 ;需要注意的是,提供的方法应该无副作用(side-effect-free),即两次执行结果相同,原因是如果由于线程争用导致更新失败会尝试再次执行该方法。
    public final int updateAndGet(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return next;
    }
    //原子性 使用 updateFunction 值 更新 value 当前值,返回 更新前的值 ;需要注意的是,提供的方法应该无副作用(side-effect-free),即两次执行结果相同,原因是如果由于线程争用导致更新失败会尝试再次执行该方法。
    public final int getAndAccumulate(int x,
                                      IntBinaryOperator accumulatorFunction) {
        int prev, next;
        do {
            prev = get();
            next = accumulatorFunction.applyAsInt(prev, x);
        } while (!compareAndSet(prev, next));
        return prev;
    }
	//原子性 使用 updateFunction 值 更新 value 当前值,返回 更新后的值 ;需要注意的是,提供的方法应该无副作用(side-effect-free),即两次执行结果相同,原因是如果由于线程争用导致更新失败会尝试再次执行该方法。
    public final int accumulateAndGet(int x,
                                      IntBinaryOperator accumulatorFunction) {
        int prev, next;
        do {
            prev = get();
            next = accumulatorFunction.applyAsInt(prev, x);
        } while (!compareAndSet(prev, next));
        return next;
    }
}

AtomicLong

引用类型

AtomicReference 原子更新引用类型,有ABA问题

AtomicStampedReference 原子更新引用类型(带时间戳,避免ABA问题)

AtomicReferenceFieldUpdater 原子更新引用类型的字段

AtomicMarkableReferce 原子更新带有标记位的引用类型 有ABA问题

数组类型

AtomicIntegerArray

AtomicLongArray

AtomicReferenceArray

字段类型

AtomicIntegerFieldUpdater

AtomicLongFieldUpdater

AtomicStampedFieldUpdater

JDK8新增原子类简介

DoubleAccumulator

LongAccumulator

DoubleAdder

LongAdder

总结

最后,简单总结下几种解决方案之间的区别:

特性 Atomic变量 volatile关键字 Lock接口 synchronized关键字
原子性 可以保障 无法保障 可以保障 可以保障
可见性 可以保障 可以保障 可以保障 可以保障
有序性 无法保障 一定程度保障 可以保障 可以保障

你可能感兴趣的:(Java,java,jvm,开发语言)