Unsafe原子性

Unsafe#

JDK 的 rt.jar 包中的 Unsafe 类提供了硬件级别的原子性操作,Unsafe 类中的方法都是 native 方法,它们使用 JNI 的方式访问本地 C++ 实现库。下面我们来了解一下 Unsafe 提供的几个主要的方法以及编程时如何使用 Unsafe 类做一些事情。

  • long objectFieldOffset(Field field)方法:返回指定的变量在所属类中的内存偏移地址,该偏移地址仅仅在该 Unsafe 函数中访问指定字段时使用。
  • boolean compareAndSwapLong(Object obj, longoffset, long expect, long update)方法:比较对象 obj 中偏移量为 offset 的变量的值是否与 expect 相等,相等则使用 update 值更新,然后返回 true,否则返回 false。
  • public native long getLongvolatile(Object obj, longoffset)方法:获取对象 obj 中偏移量为 offset 的变量对应 volatile 语义的值。
  • void putLongvolatile(Object obj, long offset, longvalue)方法:设置 obj 对象中 offset 偏移的类型为 long 的 field 的值为 value,支持 volatile 语义。

如何使用#

public class UnsafeTest {
    //获得Unsafe的一个实例
    static final Unsafe unsafe;
    static final long stateOffset;
    private volatile long state = 0;

    static {
        try {
            // 使用反射获取Unsafe的成员变量theUnsafe
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            // 设置为可存取
            field.setAccessible(true);
            // 获取该变量的值
            unsafe = (Unsafe) field.get(null);
            // 获取 UnsafeTest 类里面的 state 变量, 在 UnsafeTest 对象里面的内存偏移量地址并将其保存到 stateOffset 变量中。
            // getDeclaredFields():获得某个类的所有声明的字段
            stateOffset = unsafe.objectFieldOffset(UnsafeTest.class.getDeclaredField("state"));
        } catch (Exception e) {
            System.out.println(e.getLocalizedMessage());
            throw new Error(e);
        }
    }
    public static void main(String[] args){
        UnsafeTest unsafeTest = new UnsafeTest();
        // 如果 unsafeTest 对象中 内存偏移量为 stateOffset 的 state 变量的值为 0,则更新该值为 1
        boolean b = unsafe.compareAndSwapLong(unsafeTest, stateOffset, 0, 1);
        System.out.println(b);//true
        System.out.println(unsafeTest.state);
    }
}
本作品采用《CC 协议》,转载必须注明作者和本文链接