Atomic & Unsafe
Posted yufeng218
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Atomic & Unsafe相关的知识,希望对你有一定的参考价值。
1、Automic
1.2、 原子类分类
基本类型
- AtomicInteger:整形原子类
- AtomicLong:长整型原子类
- AtomicBoolean:布尔型原子类
- AtomicIntegerArray:整形数组原子类
- AtomicLongArray:长整形数组原子类
- AtomicReferenceArray:引用类型数组原子类
- AtomicReference:引用类型原子类
- AtomicStampedReference:原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于解决原子的更新数据和数据的版本号,可以解决使用 CAS 进行原子更新时可能出现的 ABA 问题。
- AtomicMarkableReference :原子更新带有标记位的引用类型
- AtomicIntegerFieldUpdater:原子更新整形字段的更新器
- AtomicLongFieldUpdater:原子更新长整形字段的更新器
- AtomicReferenceFieldUpdater
1.3 Atomic 的使用
以 AtomicInteger 为例:
(1)AtomicInteger 的常用方法:
public final int get() //获取当前的值 public final int getAndSet(int newValue)//获取当前的值,并设置新的值 public final int getAndIncrement()//获取当前的值,并自增 public final int getAndDecrement() //获取当前的值,并自减 public final int getAndAdd(int delta) //获取当前的值,并加上预期的值 boolean compareAndSet(int expect, int update) //如果输入的数值等于预期值,则以原子方式将该值设置为输入值(update) public final void lazySet(int newValue)//最终设置为newValue,使用 lazySet 设置之后可能导致其他线程在之后的一小段时间内还是可以读到旧的值。
(2)AtomicInteger 的实现原理
//setup to use Unsafe.compareAndSwapInt for updates(更新操作时提供“比较并替换”的作用) private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; static { try { valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } private volatile int value;
AtomicInteger 类主要利用 CAS (compare and swap) + volatile 和 native 方法来保证原子操作,从而避免 synchronized的高开销,执行效率大为提升。CAS的原理是拿期望的值和原本的一个值作比较,如果相同则更新成新的值。UnSafe 类的 objectFieldOffset()方法是一个本地方法,这个方法是用来拿到“原来的值”的内存地址,返回值是valueOffset。另外 value 是一个volatile变量,在内存中可见,因此 JVM 可以保证任何时刻任何线程总能拿到该变量的最新值。
2、Unsafe 类
2.1 介绍
实际上Atomic包里的类基本都是使用Unsafe实现的包装类。也就是上面的原子类实现过程中都会用到Unsafe类。Java中的Unsafe类提供了类似C++手动管理内存的能力。Unsafe类,全限定名是sun.misc.Unsafe,从名字可以看出来这个类对普通程序员来说是“危险”的,一般应用开发者不会用到这个类。Unsafe类是"final"的,不允许继承。且构造函数是private的,无法在外部对其进行实例化。
public final class Unsafe { private static final Unsafe theUnsafe; public static final int INVALID_FIELD_OFFSET = -1; private static native void registerNatives(); // 构造函数是private的,不允许外部实例化 private Unsafe(){ } @CallerSensitive public static Unsafe getUnsafe(){ Class var0 = Reflection.getCallerClass(); // 仅在引导类加载器`BootstrapClassLoader`加载时才合法 if(!VM.isSystemDomainLoader(var0.getClassLoader())){ throw new SecurityException("Unsafe"); } else{ return theUnsafe; } } }
那如若想使用这个类,该如何获取其实例?有如下两个可行方案。
2.2 如何使用 Unsafe 类
java -Xbootclasspath/a: ${path} // 其中path为调用Unsafe相关方法的类所在jar包路径。
public Unsafe getUnsafe() throws IllegalAccessException { try{ Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); unsafeField.setAccessible(true); Unsafe unsafe = (Unsafe) unsafeField.get(null); return unsafe; } catch (Exception e){ log.error(e.getMessage(), e); return null; } }
2.3 Unsafe 的 主要功能
原文链接:https://www.cnblogs.com/liujiarui/p/12811444.html
以上是关于Atomic & Unsafe的主要内容,如果未能解决你的问题,请参考以下文章