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