AtomicInteger

发布时间 2023-06-22 23:13:55作者: 哩个啷个波

众所周知,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

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

AtomicInteger ai = new AtomicInteger(5);

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

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

AtomicInteger ai = new AtomicInteger(5);
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

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

int val = -1;



AtomicInteger ai = new AtomicInteger(5);



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;
}

文章知识点与官方知识档案匹配,可进一步学习相关知识