Java 從字節碼的角度來看i++

一、自增操作的原子性

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。

參考

java bytecode

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章