手掌心
2018-07-15 11:04:22
@SuppressWarnings("all")public class demo1{static Integer c=0;public static void main(String[] args) throws InterruptedException {Thread a=new Thread(){@Overridepublic void run() {synchronized (c) {for (int i = 0; i < 10000; i++) {c++;} }}}; Thread b=new Thread(){@Overridepublic void run() {synchronized (c) {for (int i = 0; i < 10000; i++) {c--;}}}}; a.start();b.start();a.join();b.join();System.out.println(c);} }這是上述代碼,按理說a b線程開始啟動后,對同一個對象c進行處理,在處理并發的情況下,我用同步代碼進行同步,使線程獲取c對象才執行代碼,按理來說應該c值應該不變。但是測試 結果有偏差,而且很大,說明還是很并發的。 請各位大佬指點迷津。
2 回答

慕沐林林
TA貢獻2016條經驗 獲得超9個贊
若使對象加鎖,則需要聲明顯式對象(即顯示使用new),內存地址是確定的:
static Integer c = new Integer(0);
若使用autoboxing, 則會有不可預測的效果,因為上述代碼中在更變c變量的內存地址,使得鎖不再鎖定同一對象。
1. 從 javap -c解析的結果可以看到 Integer c = 0 編譯器使用java/lang/Integer.valueOf方法替換,再看看valueOf中有IntegerCache,當數據超過127時則使用new Integer(i);
2. 我們再看看簡單的Integer x = 0; x ++; 則會:
以上可知x++仍然會使用valueOf方法,所以鎖的對象一直變更導致同步效果失效。
注:請注意代碼風格,養成良好習慣

慕蓋茨4494581
TA貢獻1850條經驗 獲得超11個贊
static Integer c = 0;
?/**
? *?@param?args
? */
?public static void main(String[] args) {
??Integer tmp = c;
??System.out.println(tmp == c);//true
??Integer tmp2 = c++;
??System.out.println(tmp2 == c);//false
?}
- 2 回答
- 0 關注
- 580 瀏覽
添加回答
舉報
0/150
提交
取消