• 【AtomicInteger】常规用法


    众所周知,AtomicInteger用于多线程下线程安全的数据读写操作,避免使用锁同步,底层采用CAS实现,内部的存储值使用volatile修饰,因此多线程之间是修改可见的。

    1. 构造

    public AutomicInteger(int initValue): 有参构造,初始化为initValue

    public AutomicInteger(): 无参构造,相当于AutomicInteger(0)

    2. 自增1

    public int getAndIncrement(): 返回当前值,并自增1

    AtomicInteger ai = new AtomicInteger(5);

    ai.getAndIncrement(); // 5
    ai.get(); // 6

    public int incrementAndGet(): 先自增1,再返回自增后的值

    AtomicInteger ai = new AtomicInteger(5); 
    ai.incrementAndGet(); // 6
    ai.get(); // 6

    3. 自减1 

    public int getAndDecrement(): 返回当前值,并自减1

    AtomicInteger ai = new AtomicInteger(5);

    ai.getAndDecrement(); // 5
    ai.get(); // 4

     public int decrementAndGet(): 自减1, 返回自减后的值

    AtomicInteger ai = new AtomicInteger(5);

    ai.decrementAndGet(); // 4
    ai.get(); // 4

    4. 如果原来是A,则更新成B 

    public boolean compareAndSet(int source, int dest):source是改之前的值,Dest是改之后的值,source与当前真实值匹配了才能执行成功,返回值表示是否执行成功。

    AtomicInteger ai = new AtomicInteger(10);


    ai.compareAndSet(100, 12); // false, 因为改之前不是100
    ai.get(); // 10


    ai.compareAndSet(10, 12); // true

    ai.get(); // 12

    5. 自增/自减N 

    public int getAndAdd(int delta): 先获取当前值,再进行计算val = val + delta

    AtomicInteger ai = new AtomicInteger(10);
    ai.getAndAdd(2); // 10

    ai.get(); // 12

    public int addAndGet(int delta): 先计算 val = val + delta,再返回最新值

    AtomicInteger ai = new AtomicInteger(10);
    ai.addAndGet(2); // 12

    ai.get(); // 12

    当然,这个方法也支持负数参数,也就意味着可以做减法

    1. AtomicInteger ai = new AtomicInteger(5);
    2. System.out.println(ai.addAndGet(-1)); // 4

    6. 硬编码的二元计算逻辑

    public int getAndUpdate (IntUnaryOperator opeartion): 使用lambda表达式进行二元运算,获取到的是旧值。

    AtomicInteger ai = new AtomicInteger(10);
    ai.getAndUpdate(x -> x + 2); // 10, oldVal
    ai.get(); // 12

     public int updateAndGet (IntUnaryOperator opeartion): 使用lambda表达式进行二元运算,获取到的是新值。

    AtomicInteger ai = new AtomicInteger(10);
    ai.updateAndGet(x -> x + 2); // 12, newVal
    ai.get(); // 12

    当然,这里支持减法也同样没问题

    1. AtomicInteger ai = new AtomicInteger(5);
    2. System.out.println(ai.updateAndGet(val -> val - 1)); // 4

    7.  非硬编码的二元运算逻辑

    public int getAndAccumulate(int factor, IntBinaryOperator operation): 先返回旧值,再进行计算

    AtomicInteger ai = new AtomicInteger(10);
    int result = ai.getAndAccumulate(5, new IntBinaryOperator() {

        @Override
        public int applyAsInt(int left, int right){
            return left + right;
    } }); 
    
    // result = 10, 旧值
    ai.get(); // 15新值

     public int accumulateAndGet(int factor, IntBinaryOperator operation): 先计算,再返回新值

    AtomicInteger ai = new AtomicInteger(10);

    int result = ai.accumulateAndGet(5, Integer::sum); // 15
    ai.get(); // 15

    同样,这个方法的自由度大大提高

    1. int val = -1;
    2. AtomicInteger ai = new AtomicInteger(5);
    3. System.out.println(ai.accumulateAndGet(val, (a, b)-> b-a)); // -6

     

    8. 直接赋值

    public void set(int newVal): 直接更新为新值,区别于compareAndSet需要比对旧值。

    9. 直接取值

    public int get(): 取最新值

    附:

    底层的CAS是操作系统级别的实现:

    public final boolean compareAndSet(int expect, int update) {

            return unsafe.compareAndSwapInt(this, valueOffset, expect, update);

    }

    自旋式乐观锁实现数值更新

    public final int getAndAddInt(Object object, long valueOffset, int delta) {

        int currentValue;
        do {
            currentValue= this.getIntVolatile(object, valueOffset);
        } while(!this.compareAndSwapInt(object, valueOffset, currentValue,                                     currentValue + delta));
        return currentValue;
    }
    
  • 相关阅读:
    woocommerce对接paypal如何进行沙盒测试?
    Python 实现单例模式的五种写法!
    redis 队列
    数据结构(一) -- 队列
    日常工作中需要避免的9个React坏习惯
    2023 年解锁物联网端点安全
    设计模式学习(三):工厂模式
    [软件工具]opencv-svm快速训练助手教程解决opencv C++ SVM模型训练与分类实现任务支持C# python调用
    树概念及结构
    Kubernetes学习笔记-保障集群内节点和网络安全20220827
  • 原文地址:https://blog.csdn.net/Day_and_Night_2017/article/details/126239786