为什么AtomicXXX是线程安全的累计计数

effective java 第66条内容说到,累计计数i++同步问题
一种是用sync修饰符进行同步操作

另一种是使用AtomicXXX变量,如AtomicLong 的 getAndIncrement方法

好奇AtomicLong的实现,原以为也是进行同步锁操作实现的原子性。
发现源码并不是这样做的,而是使用了native方法unsafe,改方法只能在授信的代码中实例化如jdk内。
代码如下

public final long getAndIncrement() {
        while (true) {
            long current = get();
            long next = current + 1;
            if (compareAndSet(current, next))
                return current;
        }
    }

compareAndSet

public final boolean compareAndSet(long expect, long update) {
        return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
    }

可以发现当进行累加操作时,第一时间没有进行对变量的更改操作
而是将累加结果保存,通过compareAndSet方法对变量更改,
使用unsafe CAS方法判断当前值与要累加的值expect对比,如果两个变量是同一个,则进行更改操作update->当前值,否则返回false CAS存在一个ABA问题,即当判断值A是否被修改前,该值被其他线程修改成了B,然后又被修改回了A,那么CAS仍然认为该值是没有被修改过的,进行赋值操作
而getAndIncrement原理就是,不断的loop循环判断,当前值有没有在累加操作前被其他线程修改了,如果没改就赋值,改了就重新累加,再判断赋值。从而形成了类似同步的机制。保证变量的原子性。

你可能感兴趣的:(为什么AtomicXXX是线程安全的累计计数)