問(wèn):下面程序的運(yùn)行結(jié)果是什么棒假?
int count =0;
for(int i=0; i<100; i++) {
? ? count = count++;
}
System.out.println("count=" + count);
答:運(yùn)行結(jié)果是 count = 0溯职。
首先 count++ 是一個(gè)有返回值的表達(dá)式,返回值是 count 自加前的值帽哑,Java 對(duì)自加處理的流程是先把 count 的值(不是引用)拷貝到一個(gè)臨時(shí)變量區(qū)谜酒,然后對(duì) count 變量加1,接著返回臨時(shí)變量區(qū)的值妻枕。
所以上面代碼塊中第一次循環(huán)的執(zhí)行步驟是 JVM 把 count 值(0)拷貝到臨時(shí)變量區(qū)僻族,然后 count 值加 1,這時(shí) count 的值是 1屡谐,接著返回臨時(shí)變量區(qū)的值(值是 0)述么,最后返回值賦值給 count,此時(shí) count 值被重置成 0愕掏;所以上面代碼語(yǔ)句 count = count++; 可以按照如下代碼來(lái)理解:
int autoAdd(int count) {?
? ? int temp = count;
? ? count = count + 1;?
? ? return temp;
}
所以第一次循環(huán)后 count 的值還是 0度秘,其他 99 次的循環(huán)也是一樣的,最終導(dǎo)致 count 的值始終沒(méi)有改變饵撑,仍然保持著最初的狀態(tài)剑梳;如果想要打印結(jié)果為 100 則需要修改 count = count++; 語(yǔ)句為 count++; 即可。因此對(duì)于 ++/-- 運(yùn)算在 java 中一定要警惕這個(gè)陷阱(-- 運(yùn)算符也一樣存在這個(gè)問(wèn)題)滑潘,不過(guò)這個(gè)問(wèn)題在不同的語(yǔ)言環(huán)境中的實(shí)現(xiàn)是不同的垢乙,在 C++ 中 count = count++; 與 count++ 是等效的,而在 java 等語(yǔ)言中 count = count++; 與 count++ 是不等效的语卤,區(qū)別如這道題追逮。
Java
問(wèn):Java 或者 Android 開(kāi)發(fā)中可以通過(guò)哪些方式來(lái)保證并發(fā)安全的自增自減操作蓖租?
答:java 默認(rèn)的自增自減運(yùn)算符是非并發(fā)安全的,要想實(shí)現(xiàn)并發(fā)安全的自增自減操作可以通過(guò)如下幾種方式實(shí)現(xiàn)羊壹。
通過(guò) synchronized 代碼塊或者方法來(lái)保證自增自減并發(fā)安全蓖宦。
通過(guò)主動(dòng)使用 Lock 鎖來(lái)保證自增自減并發(fā)安全。
通過(guò) JDK 提供的 AtomicInteger 類來(lái)直接保證自增自減并發(fā)安全油猫。
上面幾種做法中最推薦直接使用 AtomicInteger 的方式稠茂,因?yàn)槠湎鄬?duì)于其他幾種方式封裝性非常便捷,此外其實(shí)現(xiàn)基于 volatile 對(duì)象的 CAS 操作來(lái)保證并發(fā)安全情妖,算是一種相對(duì)高效的方式