为什么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循环判断,当前值有没有在累加操作前被其他线程修改了,如果没改就赋值,改了就重新累加,再判断赋值。从而形成了类似同步的机制。保证变量的原子性。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容