Unsafe 不安全类,在并发包中使用的非常频繁,那么它究竟有什么作用呢?
Unsafe类在提升Java运行效率,增强Java语言底层操作能力方面起了很大的作用。
先来看下它是怎么使用的,下面代码摘自AQS
通过下面的代码,看起来操作不难
//初始化 直接通过静态方式获取
private static final Unsafe unsafe = Unsafe.getUnsafe();
//各种偏移量
private static final long stateOffset;
...
static {
try {
//初始化偏移量 通过使用objectFieldOffset方法
//long sun.misc.Unsafe.objectFieldOffset(Field arg0) 参数Field 获取对应字段的偏移量
stateOffset = unsafe.objectFieldOffset
(AbstractQueuedLongSynchronizer.class.getDeclaredField("state"));
headOffset = unsafe.objectFieldOffset
....
} catch (Exception ex) { throw new Error(ex); }
}
//boolean sun.misc.Unsafe.compareAndSwapObject(Object arg0, long arg1, Object arg2, Object arg3)
// 1 需要操作的类
// 2 偏移量
// 3 原始值
// 4 替换值
private final boolean compareAndSetHead(Node update) {
return unsafe.compareAndSwapObject(this, headOffset, null, update);
}
...
看过怎么使用 再来看下源码吧
1 Unsafe用的是单例模式
“
public class Unsafe {
private static Unsafe unsafe = new Unsafe();
private Unsafe() {
}
//通过安全器安全的获取unsafe
public static Unsafe getUnsafe() {
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkPropertiesAccess();
return unsafe;
}
//返回指定静态field的内存地址偏移量,在这个类的其他方法中这个值只是被用作一个访问
public native long objectFieldOffset(Field field);
//在obj的offset位置比较object field和期望的值,如果相同则更新。这个方法 的操作应该是原子的,因此提供了一种不可中断的方式更新object field。
public native boolean compareAndSwapObject(Object obj, long offset,
Object expect, Object update);
//设置obj对象中offset偏移地址对应的object型field的值为指定值。这是一个有序或者 有延迟的方法,并且不保证值的改变被其他线程立 即看到。只有在field被修饰并且期望被意外修改的时候
public native void putOrderedObject(Object obj, long offset, Object value);
// 设置obj对象中offset偏移地址对应的object型field的值为指定值。支持volatile store语义
public native void putObjectVolatile(Object obj, long offset, Object value);
// 设置obj对象中offset偏移地址对应的object型field的值为指定值。
public native void putObject(Object obj, long offset, Object value);
//获取给定数组中第一个元素的偏移地址。
public native int arrayBaseOffset(Class arrayClass);
//获取用户给定数组寻址的换算因子.一个合适的换算因子不能返回的时候(例如:基本类型), 返回0.这个返回值能够与一起使用去存取这个数组class中的元素
public native int arrayIndexScale(Class arrayClass);
//释放线程
public native void unpark(Thread thread);
// 阻塞一个线程直到出现、线程 被中断或者timeout时间到期。
public native void park(boolean isAbsolute, long time);
常用的方法一般是park、unpark、objectFieldOffset及compareAndSwapObject
省略了很多方法,不过基本差不多,这里都是调用native本地方法了。
总之呢,我们还是不要直接使用,差不多能理解就行了。