zoukankan      html  css  js  c++  java
  • Java 9 VarHandle

    VarHandle是什么?

    在看AtomicInteger源码的时候,有这么一句话:

    See the VarHandle specification for descriptions of the properties of atomic accesses.

    有关原子访问属性的描述,请参阅VarHandle规范?以前不都是Unsafe吗,怎么现在让我参考VarHandle?点进去一看,原来从Java 9开始,会尽可能用VarHandle替代Unsafe的功能。

    JDK文档对VarHandle的描述如下:

    A VarHandle is a dynamically strongly typed reference to a variable, or to a parametrically-defined family of variables, including static fields, non-static fields, array elements, or components of an off-heap data structure. Access to such variables is supported under various access modes, including plain read/write access, volatile read/write access, and compare-and-set.

    VarHandle是对变量的类型化引用,其功能是提供在不同的访问模式下对该变量的读写访问。
    变量包括静态变量,非静态变量,数组元素,堆外数据结构的成员(ByteBuffer吗?)。
    访问模式包括普通读写(plain read/write access),volatile语义读写(volatile read/write access)和CAS操作(compare-and-set)。

    那么为什么要提供VarHandle呢?

    在Java 8之前,Java提供的底层编程接口有两种,一是JNI,一是Unsafe。相比JNI,Unsafe对底层操作系统的依赖更小点,但还是有问题。sun开头的包并非Oracle官方维护的API,Oracle还计划在未来的JDK版本中删除这些API。所以使用Unsafe的代码可能会有兼容性和移植性的问题。于是有了JEP 193,该提案主要就是针对这个问题,并且,它还提出了对象字段(或类静态字段)原子操作和不安全操作的标准化接口,这就是VarHandle。

    请参考JEP 193

    简而言之,尽可能用VarHandle的API来替代Unsafe的API。

    访问模式(Access Modes)

    VarHandle文档中定义了以下几种访问类别:plain、opaque、release/acquire、volatile。它们提供了由低到高的一致性保证级别:

    • plain类型不确保内存可见性,opaque、release/acquire、volatile是可以保证内存可见的。
    • opaque保证程序执行顺序,但不保证其它线程的可见顺序。
    • release/acquire 保证程序执行顺序,setRelease确保前面的load和store不会被重排序到后面,但不确保后面的load和store重排序到前面;getAcquire确保后面的load和store不会被重排序到前面,但不确保前面的load和store被重排序。
    • volatile确保程序执行顺序,且保证变量之间不被重排序。

    VarHandle定义了以下五种访问模式,结合上面的一致性保证级别,提供了超多的方法。

    • Read access mode:get, getVolatile, getAcquire 和 getOpaque.
    • Write access mode:set, setVolatile, setRelease 和 setOpaque.
    • Atomic update access mode:compareAndSet, compareAndExchangeAcquire, compareAndExchange, compareAndExchangeRelease, getAndSet, getAndSetAcquire, getAndSetRelease, etc.
    • Numeric atomic update access mode:getAndAdd, getAndAddAcquire, getAndAddRelease.
    • Bitwise atomic update access mode:getAndBitwiseOr, getAndBitwiseOrAcquire, getAndBitwiseOrRelease, getAndBitwiseAnd, getAndBitwiseAndAcquire, getAndBitwiseAndRelease, getAndBitwiseXor, getAndBitwiseXorAcquire, getAndBitwiseXorRelease, etc.

    使用示例

    Java 9之前,我们可以使用AtomicInteger来实现线程安全的累加器:

    public class Counter {
        private AtomicInteger count = new AtomicInteger(0);
    
        public void increment() {
            this.count.getAndIncrement();
        }
    
        public int get() {
            return this.count.get();
        }
    }
    

    现在,改写成用VarHandle实现:

    public class Counter {
        private static int count = 0;
    
        public static void increment() throws IllegalAccessException, NoSuchFieldException {
            VarHandle countHandle = MethodHandles.privateLookupIn(Counter.class, MethodHandles.lookup())
                    .findStaticVarHandle(Counter.class, "count", int.class);
            countHandle.getAndAdd(1);
        }
    
        public static int get() {
            return count;
        }
    
        public static void main(String[] args) {
            int threadNum = 500;
            Thread[] threads = new Thread[threadNum];
            for (int i = 0; i < threadNum; i++) {
                threads[i] = new Thread(() -> {
                    try {
                        Counter.increment();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (NoSuchFieldException e) {
                        e.printStackTrace();
                    }
                });
            }
            for (Thread t : threads) {
                t.start();
                try {
                    t.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Counter.get());
        }
    }
    
  • 相关阅读:
    c# base64及MD5工具类
    c# dateTime格式转换为Unix时间戳工具类
    c# 金钱大写转小写工具类
    c# bitmap的拷贝及一个图像工具类
    C# DataTable映射成Entity
    Kubernetes---Service(SVC)服务--ingress api
    Kubernetes---Service(SVC)服务
    为网站文字前面添加图标 在线调用 Font Awesome 字体icon小图标 美化网站
    [转]office 2016 4合1/3合1 专业版 增强版 精简绿色安装版
    [转]数据恢复 文件恢复工具 DiskGenius v4.9.1 绿色专业版及单文件
  • 原文地址:https://www.cnblogs.com/teacherma/p/13471208.html
Copyright © 2011-2022 走看看