AtomicInteger有关自旋锁的原子性问题

AtomicInteger

    public static void main(String[] args) {
        AtomicInteger ai = new AtomicInteger(20);
        System.out.println(ai.incrementAndGet());
    }

        在学习AtominInteger时,第一次接触了CAS,也就是在自增的时候使用CAS自旋锁解决并发问题。调用的方法时incrementAndGet方法。而这个自增的操作本质上不是一个原子性操作,但是改方法在没有加synchronized的情况下实现了线程安全。下面深入学习CAS:

    /**
     * Atomically increments by one the current value.
     *  以原子性的方法,将当前值+1
     * @return the updated value
     */
    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }

        这里用到了unsafe变量,该变量比较重要,以后解答,先看getAndAddInt方法

    //操作源码,传入三个值,V,A,B,第一个V是AtomicInteger维护的变量value,表示当前数的实际值,他被volatile修饰来保证其可见性。第二个值A为当前希望操作的值,B为当前希望修改后的值。
    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
​
        return var5;
    }

        整个CAS被三个值主导:V,A,B。首先CAS,compareAndSet方法将A与实际值V进行比对,如果相等,那么就可以操作修改为B,如果不等那就放弃操作。

        这样保证了修改的一致性,但是不能保证修改的原子性,因为他有两个操作,一个是比对,第二个是修改。假设现在线程1需要将value = 1修改为2,那么比对A=1和V=1,发现相同那么修改。此时线程2比对A=1和V=1,发现也相同,把V修改为3。线程2执行完毕,而在线程1中,此时的V已经是3了,但是线程1已经经历过了比对操作,将3又修改为了2,这样就造成了严重的原子性问题。

        这里是基于HotSpot底层调用操作系统来完成原子性操作的,在操作系统执行比对并修改的CAS操作时,加上了底层锁,保证了操作原子性,而我们使用Java的时候全然不知。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Aristocrat l

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值