JUC 整理笔记四之梳理 VarHandle(上)
前面整理完 Unsafe
,不得不去了解下 java.lang.invoke.Varhandle
。如前面文章所说, Unsafe
是不建议开发者直接使用的,因为 Unsafe
所操作的并不属于Java标准,会容易带来一些安全性的问题。JDK9 之后,官方推荐使用 java.lang.invoke.Varhandle
来替代 Unsafe
大部分功能,对比 Unsafe
,Varhandle
有着相似的功能,但会更加安全,并且,在并发方面也提高了不少性能。
简介
Varhandle
是对变量或参数定义的变量系列的动态强类型引用,包括静态字段,非静态字段,数组元素或堆外数据结构的组件。 在各种访问模式下都支持访问这些变量,包括简单的读/写访问,volatile 的读/写访问以及 CAS (compare-and-set)访问。简单来说 Variable
就是对这些变量进行绑定,通过 Varhandle
直接对这些变量进行操作。
实例
目标实体类
访问 private 成员
输出
访问 protected 成员
输出
访问 public 成员
输出
访问 数组
输出
获取Varhandle方式汇总
MethodHandles.privateLookupIn(class, MethodHandles.lookup())
获取访问私有变量的LookupMethodHandles.lookup()
获取访问protected、public的Lookup
findVarHandle
:用于创建对象中非静态字段的VarHandle
。接收参数有三个,第一个为接收者的class对象,第二个是字段名称,第三个是字段类型。
findStaticVarHandle
:用于创建对象中静态字段的VarHandle
,接收参数与findVarHandle
一致。
unreflectVarHandle
:通过反射字段Field
创建VarHandle
。
MethodHandles.arrayElementVarHandle(int[].class)
获取管理数组的 Varhandle
功能
VarHandle来使用plain、opaque、release/acquire和volatile四种共享内存的访问模式,根据这四种共享内存的访问模式又分为写入访问模式、读取访问模式、原子更新访问模式、数值更新访问模式、按位原子更新访问模式。
写入访问模式(write access modes)
获取指定内存排序效果下的变量值,包含的方法有get、getVolatile、getAcquire、getOpaque 。
读取访问模式(read access modes)
在指定的内存排序效果下设置变量的值,包含的方法有set、setVolatile、setRelease、setOpaque 。
原子更新模式(atomic update access modes)
原子更新访问模式,例如,在指定的内存排序效果下,原子地比较和设置变量的值,包含的方法有compareAndSet、weakCompareAndSetPlain、weakCompareAndSet、weakCompareAndSetAcquire、weakCompareAndSetRelease、compareAndExchangeAcquire、compareAndExchange、compareAndExchangeRelease、getAndSet、getAndSetAcquire、getAndSetRelease 。
数值更新访问模式(numeric atomic update access modes)
数字原子更新访问模式,例如,通过在指定的内存排序效果下添加变量的值,以原子方式获取和设置。 包含的方法有getAndAdd、getAndAddAcquire、getAndAddRelease 。
按位原子更新访问模式(bitwise atomic update access modes )
按位原子更新访问模式,例如,在指定的内存排序效果下,以原子方式获取和按位OR变量的值。 包含的方法有getAndBitwiseOr、getAndBitwiseOrAcquire、getAndBitwiseOrRelease、 getAndBitwiseAnd、getAndBitwiseAndAcquire、getAndBitwiseAndRelease、getAndBitwiseXor、getAndBitwiseXorAcquire , getAndBitwiseXorRelease 。
内存屏障
VarHandle
除了支持各种访问模式下访问变量之外,还提供了一套内存屏障方法,目的是为了给内存排序提供更细利息的控制。主要如下几个方法:
小结
在 java9 之后,对一些变量的并发操作时,可以考虑用 java.lang.invoke.VarHandle
来处理,而不是通过 Unsafe
类来处理,毕竟 Unsafe
不太适合直接使用。
版权声明: 本文为 InfoQ 作者【JFound】的原创文章。
原文链接:【http://xie.infoq.cn/article/18c57e1a23f347a922547177b】。文章转载请联系作者。
评论