i++ 和 ++i 是否为原子操作(Java基础)

非原子操作

举例:

public static int i = 0;
    public static volatile int count = 0;

    public static void main(String[] args) throws Exception {
        for (int j = 0; j < 10; j++) {
            new MyThread().start();
        }
        while(count != 0)
            System.out.println(i);
    }

    public static class MyThread extends Thread {
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (Exception e) {

            }
            for (int j = 0; j < 100; j++) {
                i++;
            }
            ++count;
        }
    }

理想情况,应该输出1000,而情况并非如此。

volatile 声明的变量为"可见的",一般应用于多线程中,为共享变量,但是volatile只能保证变量可见性,不能保证它的原子性。 

在Java中 ++i 或者 i++是一条语句,执行javac -encoding utf8 xxx.java 和 javap -c xxx.class 命令后,查看字节码层面上也是 iinc 1,1 这一条JVM指令。但是从底层CPU层面上,可分为3个指令操作:

1. 取数
2. 累加
3. 存储

一条指令,可以保证其原子性操作,而多条指令则是非原子性操作。

如果保证i++ 或者 ++i可以实现原子操作,则需要搭配synchronized或者J.U.C中的排他锁(如ReentrantLock等)使用。

或者采用java.util.concurrent.atomic包下的原子类,如AtomicBoolean#getAndSet(boolean value),AtomicInteger#getAndAdd(int value),

AtomicIntegerArray#getAndSet(int index, int value),AtomicLong#getAndAdd(long),AtomicLongArray#getAndAdd(int index, long value)等原子类的方法进行记录。

posted @ 2019-08-13 13:31  bobwuming  阅读(245)  评论(0)    收藏  举报