线程并发类实现工具--unsafe

1.介绍

Unsafe类提供了直接操控内存和底层线程的工作。Unsafe类是在sun.misc包下,不属于Java标准。但是很多Java的基础类库,包括一些被广泛使用的高性能开发库都是基于Unsafe类开发的,比如Netty、Cassandra、Hadoop、Kafka等。Unsafe类在提升Java运行效率,增强Java语言底层操作能力方面起了很大的作用。

2.线程的挂起与恢复

2.1 线程挂起

public native  void park(boolean isAbsolute,long time)
  1. 当isAbsolute == false,表示不是绝对时间,即time=0;
  2. 当isAbsolute == true,表示是绝对时间,当阻塞的线程经过time时间后,线程阻塞自动消除。
  3. 当调用park方法后,线程阻塞。当别的线程调用unpark或者线程中断、或者超时阻塞线程将返回。
  4. 如果在调用park方法之前已经调用了unpark方法,那么线程不会阻塞。

2.2 线程恢复

public native  void unpark(Object thread)
  1. 调用此方法使得阻塞的线程恢复运行
  2. 如果没有阻塞的线程,那么以后线程调用park()将不会阻塞

3.访问/修改对象变量值

3.1 获取对象字段的偏移量

public native long objectFieldOffset(Field f)

获取一个类字段的内存偏移地址。对于相同的类,相同的字段总是有相同的内存偏移地址。
如:

 static {
        try {
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            Class<?> tk = Thread.class;
            parkBlockerOffset = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("parkBlocker"));
            SEED = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomSeed"));
            PROBE = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomProbe"));
            SECONDARY = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
        } catch (Exception ex) { throw new Error(ex); }
    }

3.2 修改对象字段的引用

public native  void putInt(Object o,long offset,int x)
  1. Object o 是实例对象
  2. long offset是对象字段的偏移量
  3. x是要修改的值

3.3 访问对象字段的引用值

public native int getInt(Object o,long offset)
  1. Object o 是实例对象
  2. long offset是对象字段的偏移量
 public native Object getObjectVolatile(Object o,
    long offset)

与volatile原语获取字段的值

4. cas实现

public final native boolean compareAndSwapInt(Object o,
   long offset,
   int expected,
   int x)
  1. except代表期望值。如果期望值跟内存中的值相等,则更新为x。否则不做修改,返回false

延迟写实现

public native  void putOrderedObject(Object o,
   long offset,
   Object x)
public final void lazySet(V newValue) {
       unsafe.putOrderedObject(this, valueOffset, newValue);
   }

lazySet是使用Unsafe.putOrderedObject方法,这个方法在对低延迟代码是很有用的,它能够实现非堵塞的写入,这些写入不会被Java的JIT重新排序指令(instruction reordering),这样它使用快速的存储-存储(store-store) barrier, 而不是较慢的存储-加载(store-load) barrier, 后者总是用在volatile的写操作上,这种性能提升是有代价的,虽然便宜,也就是写后结果并不会被其他线程看到,甚至是自己的线程。

类似Unsafe.putOrderedObject还有unsafe.putOrderedLong等方法,unsafe.putOrderedLong比使用 volatile long要快3倍左右。.

参考
1.http://www.docjar.com/docs/api/sun/misc/Unsafe.html

猜你喜欢

转载自blog.csdn.net/ai_xiangjuan/article/details/80548473