0
点赞
收藏
分享

微信扫一扫

JUC底层工具类Unsafe,必须要了解

舍予兄 2021-09-18 阅读 89
日记本

最近我们一直在学习java高并发,java高并发中主要涉及到类位于java.util.concurrent包中,简称juc,juc中大部分类都是依赖于Unsafe来实现的,主要用到了Unsafe中的CAS、线程挂起、线程恢复等相关功能。所以如果打算深入了解JUC原理的,必须先了解一下Unsafe类。
源码:

public final class Unsafe {
  // 单例对象
  private static final Unsafe theUnsafe;

  private Unsafe() {
  }
  @CallerSensitive
  public static Unsafe getUnsafe() {
    Class var0 = Reflection.getCallerClass();
    // 仅在引导类加载器`BootstrapClassLoader`加载时才合法
    if(!VM.isSystemDomainLoader(var0.getClassLoader())) {    
      throw new SecurityException("Unsafe");
    } else {
      return theUnsafe;
    }
  }
}

从代码中可以看出,Unsafe类为单例实现,提供静态方法getUnsafe获取Unsafe实例,内部会判断当前调用者是否是由系统类加载器加载的,如果不是系统类加载器加载的,会抛出SecurityException异常。

那我们想使用这个类,如何获取呢?

可以把我们的类放在jdk的lib目录下,那么启动的时候会自动加载,这种方式不是很好。

我们学过反射,通过反射可以获取到Unsafe中的theUnsafe字段的值,这样可以获取到Unsafe对象的实例。

通过反射获取Unsafe实例

import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 * 跟着阿里p7学并发,微信公众号:javacode2018
 */
public class Demo1 {
    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) {
        System.out.println(unsafe);
    }

unsafe中的cas操作

/**
 * CAS 操作
 *
 * @param o        包含要修改field的对象
 * @param offset   对象中某field的偏移量
 * @param expected 期望值
 * @param update   更新值
 * @return true | false
 */
public final native boolean compareAndSwapObject(Object o, long offset, Object expected, Object update);

public final native boolean compareAndSwapInt(Object o, long offset, int expected,int update);

public final native boolean compareAndSwapLong(Object o, long offset, long expected, long update);

什么是CAS? 即比较并替换,实现并发算法时常用到的一种技术。CAS操作包含三个操作数——内存位置、预期原值及新值。执行CAS操作的时候,将内存位置的值与预期原值比较,如果相匹配,那么处理器会自动将该位置值更新为新值,否则,处理器不做任何操作,多个线程同时执行cas操作,只有一个会成功。我们都知道,CAS是一条CPU的原子指令(cmpxchg指令),不会造成所谓的数据不一致问题,Unsafe提供的CAS方法(如compareAndSwapXXX)底层实现即为CPU指令cmpxchg。执行cmpxchg指令的时候,会判断当前系统是否为多核系统,如果是就给总线加锁,只有一个线程会对总线加锁成功,加锁成功之后会执行cas操作,也就是说CAS的原子性实际上是CPU实现的, 其实在这一点上还是有排他锁的,只是比起用synchronized, 这里的排他时间要短的多, 所以在多线程情况下性能会比较好。

举报

相关推荐

0 条评论