初识sun.msic.Unsafe类:CAS操作的核心类

java不能直接访问操作系统底层,而是通过native本地方法来访问。Unsafe类提供了硬件级别的原子操作

juc并发包,即java.util.concurrent包,是JDK的核心工具包,是JDK1.5之后,由 Doug Lea实现并引入。整个java.util.concurrent包,按照功能可以大致划分如下:

juc-locks 锁框架

juc-atomic 原子类框架

juc-sync 同步器框架

juc-collections 集合框架

juc-executors 执行器框架

public final class Unsafe {

private Unsafe() {} //私有化构造器,外界不能访问

static {theUnsafe = new Unsafe();}



    //提供反射获取Unsafe实例的方法

public static Unsafe getUnsafe() {

Class var0 = Reflection.getCallerClass();

       if (!VM.isSystemDomainLoader(var0.getClassLoader())) {

           throw new SecurityException("Unsafe");

       }

return theUnsafe;

}



//获取var1的实际地址偏移值,是一个native本地方法

public native long objectFieldOffset(Field var1);



/**

* cas更新var2对应的属性值

* @param var1 操作的对象

* @param var2 操作的对象属性地址相对偏移值,通过var1和var2获取当前对象属性的当前值

* @param var4 期望值

* @param var5 新值

*/

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



//通过target对象和对象中元素的偏移地址在内存中找到指定元素的实际值

public native int getIntVolatile(Object target, long offset);



//获取target对象中相对偏移offset地址的值

public native int getInt(Object target, long offset);



/**

*@param target 指定内存对象

*@param offset 该内存对象中需要操作的对象偏移量

*@param expectValue 期望值expectValue

*@param newValue 新值newValue

*@return true cas更新成功 false cas更新失败

*/

public final native boolean compareAndSwapInt(Object target, long offset, int expectValue, int newValue);



/**

* getAndAddInt方法解析:拿到内存位置的最新值v,使用CAS尝试修将内存位置的值修改为目标值v+delta,如果修改失败

* 则获取该内存位置的新值v,然后继续尝试,直至修改成功

*

*@param target 内存对象

*@param offset 该内存对象中需要操作的对象偏移量

*@param var4 增量

*/

public final int getAndAddInt(Object target, long offset, int var4) {

    int var5;

    //while循环尝试更新offset对应的对象元素值,知道成功才会退出,期间一直占据cpu

    do {

//通过对象地址和相对地址获取内存数据var5即变量"value"

//不停的while循环开销很大            

var5 = this.getIntVolatile(target, offset);

    } while(!this.compareAndSwapInt(target, offset, var5, var5 + var4));

    return var5;

}



public native long allocateMemory(long l);      //分配内存



public native long reallocateMemory(long l, long l1);   //扩充内存



public native void freeMemory(long l);  //释放内存



//返回指定类型数组的第一个元素相对于数组起始地址的偏移值,例如arrayClass=String[].class

public native int arrayBaseOffset(Class arrayClass);



// 获取用户给定数组寻址的换算因子,也就是数组中元素的增量地址,是2的幂次方

public native int arrayIndexScale(Class<?> var1);   //将arrayBaseOffset与arrayIndexScale配合使用,可以定位数组中每个元素在内存中的位置。

//eg:获取array数组中下标为i的元素

//计算i位置元素的地址偏移

//long ABASE = unsafe.arrayBaseOffset(String[].class); //计算String[].class的首元素地址偏移

//int SCALE = unsafe.arrayIndexScale(String[].class); //计算每个String类型元素的增量地址

//int ASHIFT = 31 - Integer.numberOfLeadingZeros(SCALE);

//long offset = ABASE + i * SCALE; //计算偏移地址(method1)

//long offset = ABASE + i << ASHIFT; //计算偏移地址(method2)

//String obj= (String) unsafe.getObject(array, ((long) i << ASHIFT) + ABASE);



//设置obj对象中offset偏移地址对应的整型field的值为指定值。这是一个有序或者有延迟的<code>putIntVolatile</cdoe>方法,并且不保证值的改变被其他线程立即看到。只有在field被<code>volatile</code>修饰并且期望被意外修改的时候使用才有用。

public native void putOrderedInt(Object obj, long offset, int value);



//设置obj对象中offset偏移地址对应的整型field的值为指定值。支持volatile store语义

public native void putIntVolatile(Object obj, long offset, int value);



//释放被park创建的在一个线程上的阻塞

public native void unpark(Thread thread);



//阻塞一个线程直到unpark出现、线程被中断或者timeout时间到期。如果一个unpark调用已经出现了,这里只计数。timeout为0表示永不过期

public native void park(boolean isAbsolute, long time);

}

猜你喜欢

转载自blog.csdn.net/qq_33436466/article/details/107716342