今日在測(cè)試volatile與synchronized特性的時(shí)候遇到的一個(gè)坑:
? ?先上示例代碼:
?
?
圖1和圖2代碼本質(zhì)上的區(qū)別是? 新線程的i=i+1操作下多了println操作。
本質(zhì)上的流程來(lái)說(shuō)究飞。講status設(shè)置為false后應(yīng)該打印i++多次后的結(jié)果娱颊。但是由于新線程status一開(kāi)始是保存在工作內(nèi)存中驻啤。
沒(méi)有同步主內(nèi)存中的status。因此while循環(huán)會(huì)一直執(zhí)行陪每。因此圖1是正確的結(jié)果祸轮。但是圖2加了輸出操作后。發(fā)現(xiàn)while循環(huán)
中斷了莱坎。相當(dāng)于status加了volatile的效果。
以上只是驗(yàn)證前的猜測(cè)寸士,但是如果只是工作內(nèi)存的問(wèn)題,那在多次運(yùn)行的情況下碴卧,應(yīng)該是少次出現(xiàn)上述問(wèn)題弱卡,而不是一直出現(xiàn)(工作內(nèi)存會(huì)自動(dòng)同步到主內(nèi)存中,上述問(wèn)題猜測(cè)的話也是在多線程情況下會(huì)出現(xiàn)的可見(jiàn)性問(wèn)題)住册。
后來(lái)驗(yàn)證得知是因?yàn)閖it(即時(shí)編譯器對(duì)運(yùn)行的代碼做了重排序的問(wèn)題)
?
該代碼while循環(huán)婶博,即時(shí)編譯器做了優(yōu)化。運(yùn)行時(shí)變成如下代碼:
?
由此驗(yàn)證上述存在的問(wèn)題荧飞。
? ?因此說(shuō)明println能達(dá)到跟volatile的效果凡人。說(shuō)明println禁用了重排序。當(dāng)點(diǎn)擊進(jìn)println源代碼后會(huì)發(fā)現(xiàn)叹阔。
?
? ?println源碼進(jìn)行synchronized操作挠轴。這就解開(kāi)疑惑了。我們都知道synchronized會(huì)禁用重排序耳幢。因此這個(gè)小坑也算告一段落了岸晦。