首先明確,筆者在這不討論"+"號做爲字符串拼接的做用,而是做爲運算符產生的問題。
也就是說下在Java中 i+1 、 i++ 、 ++i之間的區別java
i++ 和 ++i 明顯區別於 i+1 的是前二者的i的值都增長了。
若是給 i+1 賦值的話,又存在兩種狀況:安全
int x=0;
int y=0;
while(x<10){
x = x+1;
System.out.print(x+" ");
}
System.out.println();
while(y<10){
++y;
System.out.print(y+" ");
}
複製代碼
運算結果:bash
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
複製代碼
在循環中來講,上面第一種狀況的返回值的大小等價於 ++i ;第二種狀況中 i 是不變的。多線程
這二者要放到一塊兒討論。
通俗來說,其中 i++ 是先賦值後運算; ++i 是先運算後賦值,但他們在Java中都只能做爲右值使用,不能做爲左值。併發
左值是對應(refer to)內存中有肯定存儲地址的對象的表達式的值,而右值是全部不是左值的表達式的值。
這兩個在循環中的代碼:ui
int i = 0;
int j = 0;
while(i<6){
int x = i++;
System.out.print(x+""+i+" ");
}
System.out.println();
while(j<6){
int y = ++j;
System.out.print(y+""+j+" ");
}
複製代碼
結果:atom
01 12 23 34 45 56
11 22 33 44 55 66
複製代碼
他們在寄存器中的運算過程用代碼表示以下:spa
i++ >>>
0: iconst_0
1: istore_1
2: iload_1
3: iinc 1, 1
6: istore_2
7: return
++i >>>
0: iconst_0
1: istore_1
2: iinc 1, 1
5: iload_1
6: istore_2
7: return
複製代碼
也就是說i++ 運算中,棧頂值是 0 ,++i 運算中棧頂值是 1。線程
總的來講,在 i++ 與 ++i 這兩個運算中i都是增長了的,只是 i++ 返回的值是增長前的值, ++i 返回的值是增長後的值code
1. 有一個騷操做 i = i++; while循環中出現這個基本就死循環了
int i = 0;
while (i < 2) {
i = i++;
System.out.println(i);
}
複製代碼
結果就是一堆 0,你能夠本身想一想是爲何。
對了若是你的輸出語句不換行控制檯是打印不出消息的,由於結果長度超出限制了。
2.多線程中的併發問題
i++ 與 ++i 都並不是線程安全的運算,由於這二者都不是原子操做。
到這有人可能會想,是否能夠用volatile關鍵字修飾來保證線程安全呢?答案是不能。由於volatile只能保證可見性,不能保證原子性。
那麼到底怎麼在多線程中保證這二者的線程安全呢?有兩個辦法: