一、自增操作的原子性
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。