compareAndSwap是个原子方法,原理是CAS,即将内存中的值与期望值进行比较,如果相等,就将内存中的值修改成新值并返回true。
package com.java.magic.part4.exception; import java.lang.reflect.Field; import sun.misc.Unsafe; class Target{ int intParam = 3; long longParam; String strParam; } public class UnsafeTest { private static Unsafe unsafe; static{ try { Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); unsafe = (Unsafe)field.get(null); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) throws Exception { Class clazz = Target.class; Field[] fields = clazz.getDeclaredFields(); System.out.println("fieldNameeeee:fieldOffset"); for(Field f : fields){ //获取属性偏移量,可以通过这个偏移量给属性设值 System.out.println(f.getName()+" : "+unsafe.objectFieldOffset(f)); } System.out.println("--------------------------------"); Target target = new Target(); Field intParam = clazz.getDeclaredField("intParam"); int a = (Integer) intParam.get(target); System.out.println("intParam原始值:"+a); long intParamOffset = unsafe.objectFieldOffset(intParam); System.out.println("intParam实例变量偏移量:"+intParamOffset); //intParam实例变量偏移量是offset 原始值是3,我们要改成10 System.out.println(unsafe.compareAndSwapInt(target, intParamOffset, 3, 10)); System.out.println("intParam改变之后的值:"+target.intParam); System.out.println("--------------------------------"); //这个时候已经改为10了,所以会返回false System.out.println(unsafe.compareAndSwapInt(target, intParamOffset, 3, 10)); System.out.println("--------------------------------"); Field strParam = clazz.getDeclaredField("strParam"); String str = (String) strParam.get(target); System.out.println("strParam原始值:"+str); long strParamOffset = unsafe.objectFieldOffset(strParam); System.out.println("strParam实例变量的偏移量是:"+strParamOffset); System.out.println(unsafe.compareAndSwapObject(target, strParamOffset, null, "5")); System.out.println("strParam改变之后的值:"+target.strParam); } }
运行结果如下:
compareAndSwapInt是通过调用本地方法根据字段偏移去修改对象属性的.
可以看到int是4个字节的偏移量,long是8个字节的偏移量
注意:Unsafe的对象不能直接new,这里通过反射去获取Unsafe里面的私有成员变量theUnsafe