一:获取**Unsafe类实例
    Unsafe是JDK中的一个内置的类,用于直接根据内存地址访问元素.它也提供了很多好用的方法,比如,用volatile的方式设置数组中的元素。但是,这个类的作者,不希望我们使用它,因为我们虽然我们获取到了对底层的控制权,但是也增大了风险,安全性正是Java相对于C++/C的优势。
    这个类,默认情况下,只能被由
    BootstrapClassLoader**加载器加载的类所使用.

    1. public final class Unsafe {
    2. // 单例对象
    3. private static final Unsafe theUnsafe;
    4. private Unsafe() {
    5. }
    6. @CallerSensitive
    7. public static Unsafe getUnsafe() {
    8. Class var0 = Reflection.getCallerClass();
    9. // 仅在引导类加载器`BootstrapClassLoader`加载时才合法
    10. if(!VM.isSystemDomainLoader(var0.getClassLoader())) {
    11. throw new SecurityException("Unsafe");
    12. } else {
    13. return theUnsafe;
    14. }
    15. }
    16. }

    我们可以通过下面的几行代码即可获得一个Unsafe的实例:

    1. Field singleoneInstanceField = Unsafe.class.getDeclaredField("theUnsafe");
    2. singleoneInstanceField.setAccessible(true);
    3. Unsafe unsafe = (Unsafe)singleoneInstanceField.get(null);

    二:**Unsafe类的特性

    image.png
    Unsafe提供的API大致可分为内存操作、CAS、Class相关、对象操作、线程调度、系统信息获取、内存屏障、数组操作等几类,下面将对其相关方法和应用场景进行详细介绍。

    1、通过Unsafe类可以分配内存,可以释放内存;
    类中提供的3个本地方法allocateMemory、reallocateMemory、freeMemory分别用于分配内存,扩充内存和释放内存,与C语言中的3个方法对应。

    public native long allocateMemory(long l);
    public native long reallocateMemory(long l, long l1);
    public native void freeMemory(long l);
    

    2、可以定位对象某字段的内存位置,也可以修改对象的字段值,即使它是私有的;

    3、通过Unsafe类可以分配内存,可以释放内存;

    将一个线程进行挂起是通过park方法实现的,调用 park后,线程将一直阻塞直到超时或者中断等条件出现。unpark可以终止一个挂起的线程,使其恢复正常。整个并发框架中对线程的挂起操作被封装在 LockSupport类中,LockSupport类中有各种版本pack方法,但最终都调用了Unsafe.park()方法。

    //取消阻塞线程
    public native void unpark(Object thread);
    //阻塞线程
    public native void park(boolean isAbsolute, long time);
    //获得对象锁(可重入锁)
    @Deprecated
    public native void monitorEnter(Object o);
    //释放对象锁
    @Deprecated
    public native void monitorExit(Object o);
    //尝试获取对象锁
    @Deprecated
    public native boolean tryMonitorEnter(Object o);
    

    4、CAS操作

    /**
      *  CAS
      * @param o         包含要修改field的对象
      * @param offset    对象中某field的偏移量
      * @param expected  期望值
      * @param update    更新值
      * @return          true | false
      */
    public final native boolean compareAndSwapObject(Object o, long offset,  Object expected, Object update);
    public final native boolean compareAndSwapInt(Object o, long offset, int expected,int update);
    
    public final native boolean compareAndSwapLong(Object o, long offset, long expected, long update);
    
        什么是CAS? 即比较并替换,实现并发算法时常用到的一种技术。CAS操作包含三个操作数——内存位置、预期原值及新值。执行CAS操作的时候,将内存位置的值与预期原值比较,如果相匹配,那么处理器会自动将该位置值更新为新值,否则,处理器不做任何操作。我们都知道,CAS是一条CPU的原子指令(cmpxchg指令),不会造成所谓的数据不一致问题,Unsafe提供的CAS方法(如compareAndSwapXXX)底层实现即为CPU指令cmpxchg。
    

    https://juejin.im/post/5d0651edf265da1bd3055891