保证多线程间的可见性,所以声明为volatile

  参考:https://www.cnblogs.com/duanxz/p/6097779.html

 

保证多线程间的可见性,所以声明为volatile
package com.test;

import sun.misc.Unsafe;

import java.lang.reflect.Field;

public class CASLearn {
    private static final Unsafe unsafe;
    private static final long nameOffset;
    private static final long valueOffset;
    private static final long intffset;

    //为了保证多线程间的可见性,所以声明为volatile  但是这个例子是单线程的
    private volatile String name;
    private volatile long value;
    private volatile int age;

    static {
        try {
            //unsafe无法直接调用Unsafe.getUnsafe()去获取实例,这个方法只对可信任的类才能获取。
            ///通过反射获取unsafe
            Field f = Unsafe.class.getDeclaredField("theUnsafe"); //Internal reference
            f.setAccessible(true);
            unsafe = (Unsafe) f.get(null);

            //静态代码块初始化每个属性的偏移量
            //CASLearn.class.getDeclaredField("value") 能获取到value属性的原因是java的类加载机制:
            //参考:https://blog.csdn.net/m0_38075425/article/details/81627349
            // 1.加载:读取class二进制流,将类的数据结构存储值方法区,然后新建一个class对象,用来指向该类的数据结构
            // 2.验证:确保Class文件的字节流中包含信息符合当前虚拟机要求,不会危害虚拟机自身安全。其主要包括四种验证,文件格式验证,元数据验证,字节码验证,符号引用验证
            // 3.准备:为类的静态变量分配内存,并设置默认初始值。(int初始值为0)
            // 4.解析:将类的二进制数据中的符号引用替换成直接引用
            // 5.初始化:从上到下,给类的静态变量赋值,包括执行static静态代码块
            valueOffset = unsafe.objectFieldOffset(CASLearn.class.getDeclaredField("value"));
            nameOffset = unsafe.objectFieldOffset(CASLearn.class.getDeclaredField("name"));
            intffset = unsafe.objectFieldOffset(CASLearn.class.getDeclaredField("age"));
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new Error(e);
        }
    }

    private CASLearn(String name, long value, int age) {
        this.name = name;
        this.value = value;
        this.age = age;
    }

    @Override
    public String toString() {
        return "name:" + name + "  age" + age + "   value" + value;
    }

    public static void main(String[] args) {
        CASLearn cas = new CASLearn("dh", 100L, 18);
        //原子操作:修改age 18->19
        unsafe.compareAndSwapInt(cas, intffset, 18, 19);
        //原子操作,value的值为100L,不是200L,所以不修改
        unsafe.compareAndSwapLong(cas, valueOffset, 200L, 999L);
        //原子操作,修改"dh"->"hiahiahia"
        unsafe.compareAndSwapObject(cas, nameOffset, "dh", "hiahiahia");
        //结果为:name:hiahiahia  age19   value100
        System.out.println(cas);
    }
上一篇:JDK Unsafe 源码完全注释


下一篇:go uintptr unsafe Pointer offset() 的使用