转载

jdk8的并发中用到Unsafe类功能小结

关于源码参考上次的搬运: 搬运openjdk8的sun.misc.Unsafe.java源码 `

小结: Unsafe的操作小结:

1. 分配内存
2. 数据、对象属性字段值的 set get update
3. 获取对象字段的偏移量(jdk中使用频繁)
4. CAS操作: CPU原子指令操作
5. 线程的挂起和恢复

6. 内存屏障

Unsafe类提供的操作有:

1. 分配内存

(1). 分配一个 bytes 个字节的内存空间

public native long allocateMemory(long bytes);

(2). 在内存 address 处重新分配 bytes个字节的内存

public native long reallocateMemory(long address, long bytes);

(3). 直接在内存中构造一个cls类的对象, 但不调用cls类的构造方法;

public native Object allocateInstance(Class<?> cls) throws InstantiationException;

(4). 处置从 allocateMemoryreallocateMemory 获得的内存块。 传递给此方法的 address 可以为null,在这种情况下,不采取任何措施。

public native void freeMemory(long address);

2. 数据、对象属性字段值的 set get update

  • update

直接通过内存地址,操作指定对象的属性
(1). 在指定对象或数组 o 上, 对偏移量 offset 处的属性的值 v 进行 操作, 增加的量为 delta `

public final int getAndAddInt(Object o, long offset, int delta){...}

(2). 同上, offset所在字段的值为long

public final long getAndAddLong(Object o, long offset, long delta)

(3). 替换对象o的偏移量 offset处的 值, 不论旧的值是多少, 改为新的值 newValue

public final int getAndSetInt(Object o, long offset, int newValue)

(4). 同上, 修改的类型为long

public final long getAndSetLong(Object o, long offset, long newValue)

(5). 同上, 修改类型为引用对象

public final Object getAndSetObject(Object o, long offset, Object newValue)
  • get

获取 指定内存地址 上的指定类型的数据( address )

获取 指定对象偏移地址 上的指定类型的数据(Object o , long offset )

allocateMemory(long bytes) 是分配了 bytes 个字节的内存空间;

下面的get方法是 直接内存地址 address 上获取对应类型数据. 比如: getByte(address) 从内存 address取一个Byte类型的值;

public native byte    getByte(long address);
public native short   getShort(long address);
public native int     getInt(long address);
public native char    getChar(long address);
public native long    getLong(long address);
public native float   getFloat(long address);
public native double  getDouble(long address);

public native byte    getByte(Object o, long offset);
public native byte    getByteVolatile(Object o, long offset);
public native short   getShort(Object o, long offset);
public native short   getShortVolatile(Object o, long offset);
public native int     getInt(Object o, long offset);
public native int     getIntVolatile(Object o, long offset);
public native char    getChar(Object o, long offset);
public native char    getCharVolatile(Object o, long offset);
public native float   getFloat(Object o, long offset);
public native float   getFloatVolatile(Object o, long offset);
public native long    getLong(Object o, long offset);
public native long    getLongVolatile(Object o, long offset);
public native double  getDouble(Object o, long offset);
public native double  getDoubleVolatile(Object o, long offset);
public native boolean getBoolean(Object o, long offset);
public native boolean getBooleanVolatile(Object o, long offset);
// Object对象
public native Object getObject(Object o, long offset);
public native Object getObjectVolatile(Object o, long offset);
  • set

设置 指定对象偏移地址 上的指定类型的数据-( o , offset , x )

设置 直接内存地址 上的指定类型的数据- address

public native void    putByte(long address, byte x);
public native void    putByte(Object o, long offset, byte x);
public native void    putByteVolatile(Object o, long offset, byte x);
// 省略....Short/Int/Char/Float/Long/Double/Boolean/Object](long address, x)
// 省略....[Short/Int/Char/Float/Long/Double/Boolean/Object]Volatile(long address, x)

3. 获取对象字段的偏移量(jdk中使用频繁)

(1). 在当前对象中, 根据f字段获取对象的偏移量

(jdk中多处用到, 用来获取对象中声明的实例变量-使用变量名)

public native long objectFieldOffset(Field f);

例如: AtomicInteger中获取 value

jdk8的并发中用到Unsafe类功能小结

再如: ConcurrentHashMap

jdk8的并发中用到Unsafe类功能小结

(2).静态字段的上述同功能

public native Object staticFieldBase(Field f);

4. CAS操作: CPU原子指令操作

比较和交换给定的对象 o 偏移量 offset 处的 int / long / object 的值

public final native boolean compareAndSwapInt(Object o, long offset,
                                                  int expected,
                                                  int x);
public final native boolean compareAndSwapLong(Object o, long offset,
                                                   long expected,
                                                   long x);
public final native boolean compareAndSwapObject(Object o, long offset,
                                                     Object expected,
                                                     Object x);                                    int x);

5.线程的挂起和恢复

  • park 当前线程挂起

中断当前线程,直到满足以下条件之一返回:

(1). 当前线程被别的线程 unpark
(2). 当前线程被中断: interrupted

(3). isAbsolute true: 绝对时间, 而且, 绝对时间点 time已经过去;

(4). isAbsolute false: 不是绝对时间, 纳秒时长 time 已经过去;

public native void park(boolean isAbsolute, long time);
  • unpark 恢复目标线程

对已经park了的目标线程解除阻塞. ( 若目标线程没有阻塞,则导致后续调用park不阻塞 。)

public native void unpark(Object thread);

6.内存屏障

loadFence() 表示该方法之前的所有load操作在内存屏障之前完成。

storeFence()表示该方法之前的所有store操作在内存屏障之前完成。

fullFence()表示该方法之前的所有load、store操作在内存屏障之前完成。

// Ensures lack of reordering of loads before the fence with loads or stores after the fence. 
public native void loadFence();
// Ensures lack of reordering of stores before the fence with loads or stores after the fence.
public native void storeFence();
// Ensures lack of reordering of loads or stores before the fence with loads or stores after the fence.
public native void fullFence();
原文  https://segmentfault.com/a/1190000022499712
正文到此结束
Loading...