• AtomicInteger的addAndGet(int delta)与getAndAdd(int delta)有什么区别?


    结论:区别仅在于返回的结果,修改的值是相同的,但是返回的值不同。

    看一下源码注释

     1    /**
     2      * Atomically adds the given value to the current value.
     3      *
     4      * @param delta the value to add
     5      * @return the updated value
     6      */
     7     public final int addAndGet(int delta) {
     8         return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
     9     }
    10 
    11     /**
    12      * Atomically adds the given value to the current value.
    13      *
    14      * @param delta the value to add
    15      * @return the previous value
    16      */
    17     public final int getAndAdd(int delta) {
    18         return unsafe.getAndAddInt(this, valueOffset, delta);
    19     }

      注意看下划线,一个是更新后的值,一个是更新前的值

    源码:(sun.misc.Unsafe#getAndAddInt)

    1   public final int getAndAddInt(Object object, long offset, int update) {
    2         int expect;
    3         do {
    4             expect = this.getIntVolatile(this, offset);
    5         } while (!this.compareAndSwapInt(this, offset, expect, expect + update));
    6 
    7         return expect;
    8     }

      传入的形参就不必解释了,对照上面的代码应该能看懂

      第二行,期望值

      第四行,取内存(堆)中的数据

      第五行,首先肯定要执行cas,然后就是根据返回值决定是否要继续执行。

        这里有必要解释cas的执行过程,如下

    1 int compare_and_swap(int *mem_val, int expect, int update)
    2 {
    3     int old_val;
    4     old_val = *mem_val;
    5     if(old_val == expect) *mem_val = update;
    6     return old_val;      
    7 }

       主要就是第五行,如果内存中的值和传进来的期望值相同,那就把内存中的值赋值为要更新的值,然后返回内存值。

      可能有人对参数坑位有疑惑,这个问题其实仔细思考就能猜到。

      object + offset => 定位到内存中对象属性的值

       这样,也就能和内存值关联上了

    写个demo试试

     1 import java.util.concurrent.atomic.AtomicInteger;
     2 
     3 /**
     4  * @author Alin
     5  * @date 2020/7/26
     6  */
     7 public class TestAtomicInt {
     8     static AtomicInteger count = new AtomicInteger(0);
     9 
    10     public static void main(String[] args) {
    11         //返回新值
    12         System.out.println(count.addAndGet(20));
    13         System.out.println("	cur = " + count.get());
    14         /**
    15          * public final int getAndAddInt(Object this, long offset, int update) {
    16          *         int expect;
    17          *         do {
    18          *             expect = this.getIntVolatile(this, offset);
    19          *         } while(!this.compareAndSwapInt(this, offset, expect, expect + update));
    20          *
    21          *         return expect;//返回旧值
    22          *     }
    23          */
    24         System.out.println(count.getAndAdd(2));
    25         //返回当前值
    26         System.out.println("	cur = " + count.get());
    27 
    28     }
    29 }

     结果 

      20

        cur = 20

      20

         cur = 22

  • 相关阅读:
    设计模式之组合模式
    设计模式之桥接模式
    设计模式之装饰模式
    设计模式之代理模式
    总结的一些MySQL索引相关的知识点
    软件架构设计-五视图方法论
    博客迁移
    IMDB.COM排名算法(贝叶斯公式)和Reddit评论排行算法
    利用ratchet 和 ZeroMQ 实现即时(推送)聊天的功能
    composer Ratchet 实验心得
  • 原文地址:https://www.cnblogs.com/woooodlin/p/13380806.html
Copyright © 2020-2023  润新知