2010-11-08 74 views
2

我是Java線程的新手,最近纔開始閱讀內存模型。從我對Java內存模型的理解中可以看出,編譯器可以進行優化。Java內存模型和成功的布爾值

這可能會使多線程代碼和同步變得複雜,但我的問題是爲了更簡單的事情。以這個例子爲例,因爲這兩個語句並不相互依賴,編譯器是否有可能改變try語句中代碼的排序並因此中斷檢查?

boolean success = false; 
try{ 
MyClass.someFunction(); 
success = true; 
} 
catch(Exception e){ 

} 

if(success){  
    System.out.println("Sucess!"); 
} 
else{ 
    System.out.println("Fail!"); 
} 

回答

2

從Java無法理解什麼MyClass.someFunction()做,不能安全地重新排序這一說法。事實上,大多數數據相關性檢查器由於副作用而完全不能移動到功能邊界之外。

線程是一種特殊情況,並非Java獨有的 - 數據在寄存器中結束,除非需要,否則將不會從內存中重新獲取。 Java的解決方案是transient關鍵字(類似於其他語言的volatile)。

+0

+1 - 爲了指出其他語言也具有此屬性;例如C和C++。 (這是大量多線程C/C++程序出錯的原因之一,尤其是在編譯時使用更高的優化級別。) – 2010-11-08 04:39:22

3

否.Java編譯器需要按照您所期望的操作 - 如果Myclass.someFunction()正常返回,請輸入Success!,如果發生異常,請輸入Fail!。這通常來自Java的語義,並且獨立於編譯器可能做出的任何編譯器優化(除非它可能會限制哪些優化是合法的)。

原因是Java語言規範說,在單個線程中,程序必須像從頭到尾一樣執行語句。編譯器可以自由地用各種不直觀的方式重寫程序以生成字節碼,但它必須保留這樣的錯覺:在單個線程內,它按照正確的順序正確運行在源代碼中輸入的語句。

Java語言規範可以擴展,爲多線程上下文爲好,並說每個線程必須始終看到的世界與您所有的線程中執行的正是你鍵入的源代碼相一致的狀態,但(a)這會使編寫正確的編譯器優化變得非常困難,並且許多其他有用的優化將是非法的; (b)它不會很大程度上幫助程序員,因爲它不會消除對正確同步的需求;它主要只是把破碎的節目變成不那麼明顯破碎的節目。

相反,Java內存模型定義了一個線程中的內存修改何時對其他線程可見的精確規則,並且讓編譯器可以做到它所要的。這是一個很好的折衷方案,因爲它爲程序員提供了一套可用於確保其多線程程序正確的規則,同時仍然爲編譯器編寫者提供了實現良好優化的餘地。

但是,您的問題的重點是:編譯器可以在幕後執行任何想要的操作,但不允許更改程序的含義。在單線程上下文中,程序的含義已經很好定義,不會讓編譯器做你認爲可以做的壞事。