通过 UNSAFE 来实现一个 Atomic 的 CAS 辅助类【原创】

 

public abstract class AbstractUnSafeCas<T> {

  @SuppressWarnings("unused")
  private volatile Object value;

  private static final AtomicHelper ATOMIC_HELPER;

  private final CountDownLatch countDownLatch = new CountDownLatch(1);

  static {
    ATOMIC_HELPER = new AtomicHelper();
  }

  private static class AtomicHelper {

    private static final sun.misc.Unsafe UNSAFE;

    private static final long VALUE_OFFSET;

    static {
      sun.misc.Unsafe unsafe;
      try {
        unsafe = sun.misc.Unsafe.getUnsafe();
      } catch (SecurityException tryReflectionInstead) {
        unsafe = AccessController.doPrivileged(new PrivilegedAction<Unsafe>() {
          @Override
          @SneakyThrows
          public Unsafe run() {
            Class<sun.misc.Unsafe> unsafeClass = sun.misc.Unsafe.class;
            for (Field f : unsafeClass.getDeclaredFields()) {
              f.setAccessible(true);
              Object o = f.get(null);
              if (unsafeClass.isInstance(o)) {
                return unsafeClass.cast(o);
              }
            }
            throw new NoSuchFieldError("the Unsafe");
          }
        });
      }
      try {
        VALUE_OFFSET = unsafe.objectFieldOffset(AbstractUnSafeAtomicHelper.class.getDeclaredField("value"));
      } catch (Exception e) {
        throw Throwables.propagate(e);
      }
      UNSAFE = unsafe;
    }

    public boolean casValue(AbstractUnSafeAtomicHelper<?> obj, Object expect, Object update) {
      return UNSAFE.compareAndSwapObject(obj, VALUE_OFFSET, expect, update);
    }

  }

  public boolean set(T value) {
    Preconditions.checkArgument(null != value, "The value to be setted is null");
    if (ATOMIC_HELPER.casValue(this, null, value)) {
      countDownLatch.countDown();
      return true;
    }
    return false;
  }

  @SneakyThrows
  public T get(boolean blockUntilValueIsNotNull) {
    if (blockUntilValueIsNotNull) {
      countDownLatch.await();
    }
    @SuppressWarnings("unchecked")
    T asT = (T) value;
    return asT;
  }

  @SneakyThrows
  public T get(Long timeout, TimeUnit timeUnit) {
    countDownLatch.await(timeout, timeUnit);
    @SuppressWarnings("unchecked")
    T asT = (T) value;
    return asT;
  }

}

 

posted @ 2019-12-16 12:06  FrankYou  阅读(84)  评论(0编辑  收藏