Unsafe是JAVA提供偏底层的一个工具类,提供堆外内存管理,CAS操作,线程调度等功能。

 

Unsafe这个类不能直接获取,需要用反射获取其对象。

    //反射拿到Unsafe对象
    private static Unsafe reflectGetUnsafe() {
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            return (Unsafe) field.get(null);
        } catch (Exception e) {
            return null;
        }
    }

 

Unsafe管理堆外内存的代码示例

public static void actionMemory() {
        Unsafe unsafe = reflectGetUnsafe();

        //分配10个字节的内存,返回值为内存基础地址
        long address = unsafe.allocateMemory(10);

        //传入基础地址,长度10,  byte-0,初始化堆外内存
        unsafe.setMemory(address, 10L, (byte) 0);

        //传入内存地址位置设置byte值
        unsafe.putByte(address, (byte) 1);
        unsafe.putByte(address+1, (byte) 2);
        unsafe.putByte(address+2, (byte) 3);

        //根据内存地址获取byte值
        System.out.println(unsafe.getByte(address));
        System.out.println(unsafe.getByte(address+1));
        System.out.println(unsafe.getByte(address+2));

        //释放内存
        unsafe.freeMemory(address);
}

Unsafe.getAndAddInt原子增加方法。

	//o为对象  offset为对象属性的内存地址   delta为数值
	public final int getAndAddInt(Object o, long offset, int delta) {
        int v;
        do {
			//v为旧值,这里可能并发,多个线程同时拿到相同的值
            v = getIntVolatile(o, offset);
			
			//传入旧值v 跟新值v + delta,这里也是并发调用
			//compareAndSwapInt方法保证只有一个线程能够对变量赋值v + delta,
			//那么此时其它线程传入的仍然是旧值V,显然不会成功,那么会继续循环
        } while (!compareAndSwapInt(o, offset, v, v + delta));
        return v;
    }
Unsafe.compareAndSwapInt方法,传入预期值和新值,如果变量的值等于预期值才会把新值赋值给变量,此方法虚拟机底层实现,保证了现场安全,不会有俩个线程同时更新。
public final native boolean compareAndSwapInt(Object o, long offset,
                                                  int expected,
                                                  int x);