• 【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;
    }
    
  • 相关阅读:
    互联网大厂java面试题一美团
    智能垃圾桶(七)——SG90舵机的介绍与使用(树莓派pico实现)
    QTableView获取可见的行数
    电脑WIFI突然消失
    golang学习笔记系列之go语言代码的组织
    Codeforces Round 753 (Div. 3)(集训队加训2)
    Web系统常见安全漏洞介绍及解决方案-XSS攻击
    java学习笔记(2)
    python经典百题之一个素数能被几个9整除
    与归并排序相关的一些问题
  • 原文地址:https://blog.csdn.net/Day_and_Night_2017/article/details/126239786