i++的原子性问题

一、什么是原子性

  简单的可以理解为:操作是不可再分割的,比如;

int i=0;

但是i++的操作是可以再分的,比如:

i++ 
//分解后
i=i+i

上面的代码在多线程环境下取值是有问题的,比如:

package com.example.demo.juc;

/**
 * @author DUCHONG
 * @since 2019-01-07 19:11
 **/
public class AtomicTest {

    public static void main(String[] args) {

        AtomicThread atomicTest=new AtomicThread();
        for (int i=1;i<=20;i++){

            new Thread(atomicTest).start();
        }
    }
}

class AtomicThread implements Runnable {

    private  int num=1;
    @Override
    public void run() {
        try {
            Thread.sleep(300);
            System.out.println(getNum());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public int getNum(){
        return num++;
    }
}

结果:

这种问题当然可以通过加synchronized 关键字来解决,那有没有另外一种方案呢,答案肯定是有的,且在jdk1.5的时候就有了,那就是Atomic包下的原子类

优化后:

package com.example.demo.juc;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author DUCHONG
 * @since 2019-01-07 19:11
 **/
public class AtomicTest {

    public static void main(String[] args) {

        AtomicThread atomicTest=new AtomicThread();
        for (int i=1;i<=20;i++){

            new Thread(atomicTest).start();
        }
    }
}

class AtomicThread implements Runnable {

    private AtomicInteger at=new AtomicInteger(1);
    @Override
    public void run() {
        try {
            Thread.sleep(300);
            System.out.println(getNum());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public int getNum(){
        return at.getAndIncrement();
    }
}

看源码:

构造函数中的值,是volatile类型的

自增或者自减时,使用了CAS算法,CAS算法有三个操作数:

内存值:A

预估值:B

新值:V 

当且仅当 A=B 是 A=V 

否则不做任何操作。

原文地址:https://www.cnblogs.com/geekdc/p/10235283.html