• 源码学习:AtomicInteger类代码内部逻辑


    1. AtomicInteger是什么

    一个可以原子更新的int值。有关原子变量属性的描述,请参阅java.util.concurrent.atomic包规范。AtomicInteger用于原子递增计数器等应用程序,不能用作Integer的替代品。但是,这个类确实扩展了Number,以允许处理基于数字的类的工具和实用程序进行统一访问。

    2. 设置使用CAS进行更新

    setUp to use Unsafe.compareAndAwapInt for update

    3. 计算偏移量

    检查用户权限获取声明为公有的字段,然后根据有权限的字段,获取系统的偏移量value得到一个long类型的偏移量的值

    static {
            try {
                valueOffset = unsafe.objectFieldOffset
                    (AtomicInteger.class.getDeclaredField("value"));
            } catch (Exception ex) { throw new Error(ex); }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4. 懒赋值

     /**
         * Eventually sets to the given value. 最后的时候进行赋值操作
         *
         * @param newValue the new value
         * @since 1.6
         */
        public final void lazySet(int newValue) {
            unsafe.putOrderedInt(this, valueOffset, newValue);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    5. getAndSet 先获取然后再进行赋值操作(涉及CAS)

    public final int getAndSetInt(Object var1, long var2, int var4) {
            int var5;
            do {
                var5 = this.getIntVolatile(var1, var2);
            } while(!this.compareAndSwapInt(var1, var2, var5, var4));
    
            return var5;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    第一步:传入一个要替换的值var5;然后计算根据var1和war2通过getIntVolatile计算得到var5
    第二步:如果compareAndSwapInt比较结果和var5相等,返回var5

    6. compareAndSet

       /**
         * Atomically sets the value to the given updated value
         * if the current value {@code ==} the expected value.
         * 
         * @param expect the expected value
         * @param update the new value
         * @return {@code true} if successful. False return indicates that
         * the actual value was not equal to the expected value.
         */
        public final boolean compareAndSet(int expect, int update) {
            return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    如果实际要更新的值和预期要更新的值不想等则返回false,如果实际要更新的值和期待值相等返回true

    7. 获取并更新值

    第一步:

     /**
         * Atomically adds the given value to the current value.
         *
         * @param delta the value to add
         * @return the updated value
         */
        public final int addAndGet(int delta) {
            return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    第二步:

     public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
    
        return var5;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果原来值var1和偏移量var2得到的计算和结果var5相等,给var5加上相应的增量delta即var4

    8.getAndUpdate

    public final int getAndUpdate(IntUnaryOperator updateFunction) {
            int prev, next;
            do {
                prev = get();
                next = updateFunction.applyAsInt(prev);
            } while (!compareAndSet(prev, next));
            return prev;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    用应用给定函数的结果原子地更新当前值,返回跟新前的值。该函数应该没有副作用,因为当线程争用导致尝试更新失败时,会重新尝试更新。

    9.updateAndGet

     public final int updateAndGet(IntUnaryOperator updateFunction) {
            int prev, next;
            do {
                prev = get();
                next = updateFunction.applyAsInt(prev);
            } while (!compareAndSet(prev, next));
            return next;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    用应用给定函数的结果原子地更新当前值,返回跟新后的值。该函数应该没有副作用,因为当线程争用导致尝试更新失败时,会重新尝试更新。

    10.getAndAccumulate

    public final int getAndAccumulate(int x, IntBinaryOperator accumulatorFunction) {
            int prev, next;
            do {
                prev = get();
                next = accumulatorFunction.applyAsInt(prev, x);
            } while (!compareAndSet(prev, next));
            return prev;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    用将给定函数应用于当前值和给定值的结果原子地更新当前值,返回更新前的值。该函数应该没有副作用,因为当线程争用导致尝试更新失败时,可能会重新应用该函数。函数的第一个参数是当前值,第二个参数是给定的更新。

    11. accumulateAndGet

    public final int accumulateAndGet(int x, IntBinaryOperator accumulatorFunction) {
            int prev, next;
            do {
                prev = get();
                next = accumulatorFunction.applyAsInt(prev, x);
            } while (!compareAndSet(prev, next));
            return next;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    用将给定函数应用于当前值和给定值的结果原子地更新当前值,返回跟新后的值。该函数应该没有副作用,因为当线程争用导致尝试更新失败时,可能会重新应用该函数。函数的第一个参数是当前值,第二个参数是给定的更新。

  • 相关阅读:
    ResultMap详解(处理字段名和属性名不一致)
    “系统重要性银行”光环下,南京银行的重重忧思
    Java的finalize方法探究
    <JDBC> 批量插入 的四种实现方式:你真的get到了吗?
    TypeScript学习 + 贪吃蛇项目
    QMetaObject::invokeMethod与QThreadPool线程池使用
    idea未知的解决方案
    2022年8月最新运维面试题-服务器上下架流程
    css3实现图片瀑布流,根据屏幕大小列可变和不可变的的瀑布流
    【JavaScript】jstree使用以及本地化
  • 原文地址:https://blog.csdn.net/m0_55284524/article/details/125431011