Java 原子类的操作 AtomicInteger

947 阅读3分钟

最近研究 Java 的并发包,了解到关于原子类的操作,这里将自己了解到的贴出来功能大家参考一下,有什么不足的地方还望大家指正,及时更新。

AtomicInteger 是 Java 1.5 开始在 atomic 包提供的可以在多线程条件下安全的访问和操作 int 数据类型的类,之前我们对操作 int 数据类型的时候,通常用 i++、i-- 等操作,但是这样的操作在多线程下是不安全的,因为这样的操作并不是原子的,下面我们看看例子:

public class IntegerTest {
    private static int number = 0;
    private final ststic int count = 1000000;

    public static void main(String[] args){
        Runnable runnable1 = createRunnable();
        Runnable runnable2 = createRunnable();
    
        //这里执行 2000000 次
        new Thread(runnable1).start();
        new Thread(runnable2).start();
    
        try{
            Thread.sleep(1000);
            // 打印
            System.out.println(number);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static Runnable createRunnable(){
        return ()->{
            for(int i = 0; i < count; i++){
                number++;
            }
        }
    }
}

经测试,最后的打印结果是:1048708。当然,每次打印的值都不一样,但是这正说明了在多线程下,针对 int 的操作是不安全的。

以后针对这样的场景可以使用 AotmicInteger 类,它帮助我们解决了多线程下的安全问题,并且提供了更所的操作方法,下面介绍一下这个类的方法介绍:

1、byteValue() —— 这个方法继承自 Number 类,以 byte 类型返回当前值;
2、shortValue() —— 这个方法继承自 Number 类,以 short 类型返回当前值;
3、intValue() —— 这个方法继承自 Number 类,以 int 类型返回当前值;
4、longValue() —— 这个方法继承自 Number 类,以 long 类型返回当前值;
5、floatValue() —— 这个方法继承自 Number 类,以 float 类型返回当前值;
6、doubleValue() —— 这个方法继承自 Number 类,以 double 类型返回当前值;

7、getAndIncrement() —— 这个方法先获取当前值,然后再自增 1 (类似 i++);
8、incrementAndGet() —— 这个方法先自增 1 (类似 ++i),然后再返回这个值;
9、getAndIncrement() —— 这个方法先获取当前值,然后再自减 1 (类似 i--);
10、incrementAndGet() —— 这个方法先自减 1 (类似 --i),然后再返回这个值;

11、addAndGet(int value) —— 先加上 value,然后返回之后的值;
12、getAndAdd(int value)—— 先获取当前值,然后自己在加上 value;

//从这儿我们可以发现这个类的方法命名很直观,从名字就能知道这个方法的作用

13、compareAndSet(int first, int second) —— 如果当前值等于 first,返回 true,同时将值更新为 second,
否则返回 false,但不会更新;
14、weakCompareAndGet(int first, int second) —— 与 compareAndSet 一样(源码是一样);

15、getAndSet(int value) —— 先获取当前值,然后再设置为 value;

16、getAndUpdate(IntUnaryOperator op) —— 这个方法是 Java 1.8 开始提供的,这个方法自身返回当前值。
同时会把 op 的返回值设置为新值,具体参考 IntUnaryOperator 类,关于 function 包使用方法以后会介绍;
17、updateAndGet(IntUnaryOperator op) —— 这个方法先将 op 的返回值作为新值,然后返回这个新值;

18、getAndAccumulate(int val, IntBinaryOperator op) —— 这个方法返回值,然后将当前值和 val 作为参数传给 op,
将 op 的返回值设置为新值;
19、accumulateAndGet(int val, IntBinaryOperator op) —— 这个方法先将当前值和 val 作为参数传给 op,
将 op 的返回值设置为新值,然后返回;

20、set(int val) —— 设置;
21、lazySet(int val) —— 设置(与 set 一样,区别暂时还不知,但实现方式不一样)。

以上就是 AtomicInteger 类的全部方法了,但是我在阅读源码的时候还发现了一些疑惑的地方,比如 getAndAccumulate 方法在内部的实现中循环调用了 compareAndSet 方法,这儿有什么必要循环调用呢?暂时还不清楚,但这大概就是我们是我们在探索的道路上越走越远的一大动力吧!以后有什么新的发现会及时更新,如有人清楚,还望告知。

谢谢大家,请大家持续关注!