zoukankan      html  css  js  c++  java
  • AtomicIntegerArray 源码分析

    AtomicIntegerArray

    AtomicIntegerArray 能解决什么问题?什么时候使用 AtomicIntegerArray?

    可以用原子方式更新其元素的 int 数组
    

    如何使用 AtomicIntegerArray?

    1)多线程环境下需要对整形数组中的单个值执行原子更新时使用 AtomicIntegerArray。
    

    使用 AtomicIntegerArray 有什么风险?

    1)高并发场景下,自旋 CAS 长时间失败会导致 CPU 飙升
    

    AtomicIntegerArray 核心操作的实现原理?

    创建实例

        private static final VarHandle AA
        = MethodHandles.arrayElementVarHandle(int[].class);
        
        /**
         * 存储 int 值的数组 
         */
        private final int[] array;
    
        /**
         * 创建给定长度的新 AtomicIntegerArray 实例,所有元素的值都为 0。
         */
        public AtomicIntegerArray(int length) {
            array = new int[length];
        }
    

    读取指定索引处的值

        /**
         * 读取指定索引处的值
         * with memory effects as specified by {@link VarHandle#getVolatile}.
         */
        public final int get(int i) {
            return (int)AtomicIntegerArray.AA.getVolatile(array, i);
        }
    

    以原子方式将索引 i 处的元素值加 1,并返回旧值

        /**
         * 以原子方式将索引 i 处的元素值加 1,并返回旧值
         * with memory effects as specified by {@link VarHandle#getAndAdd}.
         */
        public final int getAndIncrement(int i) {
            return (int)AtomicIntegerArray.AA.getAndAdd(array, i, 1);
        }
    

    以原子方式将索引 i 处的元素值减 1,并返回旧值

        /**
         * 以原子方式将索引 i 处的元素值减 1,并返回旧值
         * with memory effects as specified by {@link VarHandle#getAndAdd}.
         */
        public final int getAndDecrement(int i) {
            return (int)AtomicIntegerArray.AA.getAndAdd(array, i, -1);
        }
    

    以原子方式将索引 i 处的元素值加 delta,并返回旧值

        /**
         * 以原子方式将索引 i 处的元素值加 delta,并返回旧值
         * with memory effects as specified by {@link VarHandle#getAndAdd}.
         */
        public final int getAndAdd(int i, int delta) {
            return (int)AtomicIntegerArray.AA.getAndAdd(array, i, delta);
        }
    

    以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值】计算后的新值,并返回旧值

        /**
         *  以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值】计算后的新值,并返回旧值
         */
        public final int getAndUpdate(int i, IntUnaryOperator updateFunction) {
            int prev = get(i), next = 0;
            for (boolean haveNext = false;;) {
                if (!haveNext) {
                    next = updateFunction.applyAsInt(prev);
                }
                if (weakCompareAndSetVolatile(i, prev, next)) {
                    return prev;
                }
                haveNext = prev == (prev = get(i));
            }
        }
    

    以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值和参考值】计算后的新值,并返回旧值

        /**
         * 以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值和参考值】计算后的新值,并返回旧值
         */
        public final int getAndAccumulate(int i, int x,
                IntBinaryOperator accumulatorFunction) {
            int prev = get(i), next = 0;
            for (boolean haveNext = false;;) {
                if (!haveNext) {
                    next = accumulatorFunction.applyAsInt(prev, x);
                }
                if (weakCompareAndSetVolatile(i, prev, next)) {
                    return prev;
                }
                haveNext = prev == (prev = get(i));
            }
        }
    

    以原子方式将索引 i 处的元素值加 1,并返回新值

        /**
         * 以原子方式将索引 i 处的元素值加 1,并返回新值
         * with memory effects as specified by {@link VarHandle#getAndAdd}.
         */
        public final int incrementAndGet(int i) {
            return (int)AtomicIntegerArray.AA.getAndAdd(array, i, 1) + 1;
        }
    

    以原子方式将索引 i 处的元素值减 1,并返回新值

        /**
         * 以原子方式将索引 i 处的元素值减 1,并返回新值
         * with memory effects as specified by {@link VarHandle#getAndAdd}.
         */
        public final int decrementAndGet(int i) {
            return (int)AtomicIntegerArray.AA.getAndAdd(array, i, -1) - 1;
        }
    

    以原子方式将索引 i 处的元素值加 delta,并返回新值

        /**
         * 以原子方式将索引 i 处的元素值加 delta,并返回新值
         * with memory effects as specified by {@link VarHandle#getAndAdd}.
         */
        public final int addAndGet(int i, int delta) {
            return (int)AtomicIntegerArray.AA.getAndAdd(array, i, delta) + delta;
        }
    

    以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值】计算后的新值,并返回新值

        /**
         *  以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值】计算后的新值,并返回新值。
         */
        public final int updateAndGet(int i, IntUnaryOperator updateFunction) {
            int prev = get(i), next = 0;
            for (boolean haveNext = false;;) {
                if (!haveNext) {
                    next = updateFunction.applyAsInt(prev);
                }
                if (weakCompareAndSetVolatile(i, prev, next)) {
                    return next;
                }
                haveNext = prev == (prev = get(i));
            }
        }
    

    以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值和参考值】计算后的新值,并返回新值

        /**
         *  以原子方式将索引 i 处的元素值更新为函数式接口【参数为旧值和参考值】计算后的新值,并返回新值
         */
        public final int accumulateAndGet(int i, int x,
                IntBinaryOperator accumulatorFunction) {
            int prev = get(i), next = 0;
            for (boolean haveNext = false;;) {
                if (!haveNext) {
                    next = accumulatorFunction.applyAsInt(prev, x);
                }
                if (weakCompareAndSetVolatile(i, prev, next)) {
                    return next;
                }
                haveNext = prev == (prev = get(i));
            }
        }
    
  • 相关阅读:
    mysql 数据库集群连接配置
    tomcat server.xml 配置优化
    使用PowerDesigner16.5 逆向数据库生产表结构或导出word文档
    SpringBoot、thymeleaf 国际化配置
    解决 SpringBoot 跨域请求问题
    在 centos7 系统中用 docker 创建 tomcat 服务镜像
    JAVA 调用 com.google.protobuf
    登录后获取token,作为参数传入下一个操作
    通过二进制数据流方式上传图片及性能测试脚本编写
    信息服务(ISS)管理器之报错【"/"应用程序中的服务器错误。】
  • 原文地址:https://www.cnblogs.com/zhuxudong/p/10053776.html
Copyright © 2011-2022 走看看