A collection of methods for performing low-level, unsafe operations. Although the class and all methods are public, use of this class is limited because only trusted code can obtain instances of it.
这是 Unsafe 类的注释,可见 JDK 是不推荐我们直接使用 Unsafe 的实例的,它是一系列低层次(比如针对内存的直接操作)操作的方法集合;所谓的 Unsafe 的含义是该类的实例可以绕开 JVM 的束缚直接操作内存,并且提供 CPU 指令 CAS 原子操作级别的支持,如果被一些不了解情况的人使用,会出现意想不到的异常情况,往往是致命的。
Java 的设计是不能直接操作底层操作系统,而是通过 native 方法去操作,这也是 JVM 的核心能力;但是 Unsafe 提供了一些更加高效的方式来使用 CPU 指令和操作内存空间。
double-regiseter 模式是一种双地址模式,需要 o 和 offset 一起配合才能找到要操作的对象(或者内存地址),JVM 堆中的对象一般需要这种方式来操作。
什么是 CAS? 即比较并替换,实现并发算法时常用到的一种技术。CAS 操作包含三个操作数 —— 内存位置、预期原值及新值。执行 CAS 操作的时候,将内存位置的值与预期原值比较,如果相匹配,那么处理器会自动将该位置值更新为新值,否则,处理器不做任何操作。我们都知道,CAS 是一条 CPU 的原子指令(cmpxchg指令),不会造成所谓的数据不一致问题,Unsafe 提供的 CAS 方法(如compareAndSwapXXX)底层实现即为 CPU 指令 cmpxchg。
// 对象的 CAS 操作,o 的 offset 位置是一个对象成员,如果是excepted就更新为xpublicfinalnativebooleancompareAndSwapObject(Object o,long offset,Object expected,Object x);// 对象的 CAS 操作,o 的 offset 位置是一个int类型的成员publicfinalnativebooleancompareAndSwapInt(Object o,long offset,int expected,int x);// 对象的 CAS 操作,o 的 offset 位置是一个long类型的成员publicfinalnativebooleancompareAndSwapLong(Object o,long offset,long expected,long x);// 自旋+CAS的典型用法,lock-free算法的精髓所在publicfinalintgetAndAddInt(Object o,long offset,int delta) {int v;// 自旋判断是期望的最新值就更新,如果不是就自旋,直到成功do {// 取到最新的值 v =getIntVolatile(o, offset);// 尝试增加 delta,因为在多线程情况下,有可能存在竞态条件,使用自旋不断尝试 } while (!compareAndSwapInt(o, offset, v, v + delta));return v;}// 和 getAndAddInt 类似publicfinallonggetAndAddLong(Object o,long offset,long delta) {long v;do { v =getLongVolatile(o, offset); } while (!compareAndSwapLong(o, offset, v, v + delta));return v;}// 原子性的设置指定位置的值为新的值,同样是自旋 + CASpublicfinalintgetAndSetInt(Object o,long offset,int newValue) {int v;do { v =getIntVolatile(o, offset); } while (!compareAndSwapInt(o, offset, v, newValue));return v;}publicfinallonggetAndSetLong(Object o,long offset,long newValue) {long v;do { v =getLongVolatile(o, offset); } while (!compareAndSwapLong(o, offset, v, newValue));return v;}publicfinalObjectgetAndSetObject(Object o,long offset,Object newValue) {Object v;do { v =getObjectVolatile(o, offset); } while (!compareAndSwapObject(o, offset, v, newValue));return v;}
线程调度操作
// 这是和线程调度相关的本地方法,和线程的状态切换有关系// unpark 是将某个线程从 WAITING or TIMED_WAITING 状态激活,线程重新可以被调度,在就绪队列排队// 竞争CPUpublicnativevoidunpark(Object thread);// park 将某个线程从 Runnable 状态转成 WAITING or TIMED_WAITING,// 线程等待被激活或者超时时间到后进入就绪队列publicnativevoidpark(boolean isAbsolute,long time);// 方法 park、unpark 即可实现线程的挂起与恢复,将一个线程进行挂起是通过 park 方法实现的,// 调用 park 方法后,线程将一直阻塞直到超时或者中断等条件出现;// unpark 可以终止一个挂起的线程,使其恢复正常。