并发编程之Unsafe魔术类的魔术

unsafe这个类是Jdk中底层的一个类,主要可以用于操作底层的内存,cas,数组,对象,内存操作,等一些可以跨过JVM底层操作。也就是因为能够对内存操作,自然就会引发一些不安全问题。所有叫做unsafe。
unsafe是不能new的因为它的构造函数是私有的,另外如果要使用getUnsafe()这个方法,就必须要保证类加载器是启动类加载器,

private Unsafe() {
    }

    @CallerSensitive
    public static Unsafe getUnsafe() {
        Class var0 = Reflection.getCallerClass();
        if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
            throw new SecurityException("Unsafe");
        } else {
            return theUnsafe;
        }
    }

并发编程之Unsafe魔术类的魔术
还有获取unsafe这个类的实例的方法是通过反射;

 public static Unsafe reflectGetUnsafe() {
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            return (Unsafe) field.get(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

1. 内存操作

内存操作类似于C++中的malloc方法,需要自己手动分配内存和释放内存。

 public static void main(String[] args) {

        Unsafe unsafe = UnsafeInstance.reflectGetUnsafe();

        long oneHundred = 1;
        byte size = 1;

        /*
         * 调用allocateMemory分配内存
         */
        long memoryAddress = unsafe.allocateMemory(size);

        /*
         * 将1写入到内存中
         */
        unsafe.putAddress(memoryAddress, oneHundred);

        /*
         * 内存中读取数据
         */
        long readValue = unsafe.getAddress(memoryAddress);

        System.out.println("value : " + readValue);
    }

CAS操作

cas操作是并发编程中的核心,也是在unsafe类中实现的。底层是基于CMPXCHG指令的操作。

  public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);

    public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

    public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

可以实现根据偏移量地址找到变量实现原子操作。

public class AtomicStudentAgeUpdater {
    private String name ;
    private volatile int age;

    private static final Unsafe unsafe = UnsafeInstance.reflectGetUnsafe();
    private static final long valueOffset;

    static {
        try {
            valueOffset = unsafe.objectFieldOffset(AtomicStudentAgeUpdater.class.getDeclaredField("age"));
            System.out.println("valueOffset:--->"+valueOffset);
        } catch (Exception e) {
            throw new Error(e);
        }
    }

    public void compareAndSwapAge(int old,int target){
        unsafe.compareAndSwapInt(this,valueOffset,old,target);
    }


    public AtomicStudentAgeUpdater(String name,int age){
        this.name = name;
        this.age = age;
    }

    public int getAge(){
        return this.age;
    }

    public static void main(String[] args) {
        AtomicStudentAgeUpdater updater = new AtomicStudentAgeUpdater("杨过",18);
        updater.compareAndSwapAge(18,56);

        System.out.println("真实的杨过年龄---"+updater.getAge());

    }
}
输出
valueOffset:--->12
真实的杨过年龄---56

线程调度

  public native void unpark(Object var1);
  public native void park(boolean var1, long var2);
 /** @deprecated */
    @Deprecated
    public native void monitorEnter(Object var1);
    /** @deprecated */
    @Deprecated
    public native void monitorExit(Object var1);
    /** @deprecated */
    @Deprecated
    public native boolean tryMonitorEnter(Object var1);

park和unpark是线程挂起和恢复操作。

内存屏障

   public native void loadFence();
    public native void storeFence();
    public native void fullFence();

CPU和编译器堆内存随机访问操作的同步点,此点之前的所有的读写操作都执行之后才进行之后的操作。避免了指令重排序。

并发编程之Unsafe魔术类的魔术并发编程之Unsafe魔术类的魔术 islandlxl 发布了9 篇原创文章 · 获赞 1 · 访问量 619 私信 关注
上一篇:c# – 如果抛出异常,“固定”是否可以正确清理?


下一篇:Java基础之CAS深入解析