一、自增操作的原子性
Java中i++是否是原子的? 答案当然是否定的,java中的自增操作并不是原子的,具体的原因,可以通过查看java字节来了解。
public class Main {
private int i = 0;
public void inc() {
i++;
}
}
javap看一下对应的字节码
0 aload_0 # 载入this指针到当前栈
1 dup # 复制栈顶数据
2 getfield #2 <com/alibaba/rhino/dcc/Main.i> 获取i属性压栈
5 iconst_1 # 栈顶压栈常量1
6 iadd # i在栈内+1后压栈
7 putfield #2 <com/alibaba/rhino/dcc/Main.i> 把栈顶的值赋值给属性i
10 return
很明显,i++操作过程是多步指令完成的,i++并不是原子操作,因此在开发过程中如果需要原子+/-建议使用AtomicInteger。
二、一个小case
了解的i++是非原子的操作,那么下面来看一个小例子
public class Main {
public static void main(String[] args) {
int i = 0;
i = i++;
System.out.println(i);
}
}
输出结果该是怎样的呢? 答案是0
同样的,如果无法理解,可以尝试从字节码的角度来看一下
0 iconst_0 # 栈顶载入0
1 istore_1 # 把栈顶的0写入临时变量数组1的位置 -> i=0
2 iload_1 # 把临时变量区1位置的值压栈,此时栈顶元素值为0
3 iinc 1 by 1 # 把临时变量去的1做+1操作,此时临时变量区的i=1
6 istore_1 #把栈顶的元素(0)写入到临时变量区1位置 i = 0
7 getstatic #2 <java/lang/System.out>
10 iload_1
11 invokevirtual #3 <java/io/PrintStream.println>
14 return
从字节码上来看,最终的结果确实为0。