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 协议》,转载必须注明作者和本文链接