爲什麼新線程對主線程進行的變量修改沒有察覺?
1、JIT編譯器對新線程的代碼進行優化,導致新線程在線程上下文中察覺不到變量的修改
2、新線程可能會從本地緩存或是寄存器中獲取變量數據,而不是從速度更慢的內存中獲取
volatile 關鍵字如何保證內存可見性?
volatile標記的變量,會警告JIT編譯器,標記volatile標記的變量可能會被其他線程修改,不要執行任何可能影響其訪問順序的優化。
也就是說:線程每次獲取該變量數據的時候,都要從內存中獲取。
但是每次都從內存中獲取,會導致程序性能的降低,而且多線程的請款下,對volatile變量的訪問時各自獨立處理的,這些訪問很難一直統一,因此也無法保證整體操作的原子性。
小結:
1、volatile修飾的變量保證內存可見性
2、volatile修飾的變量不會進行指令重排
備註:
什麼是JIT?
just in time,即時編譯編譯器。
java代碼執行的時候,會先通過javac命令將代碼編譯成class文件,到之後執行,代碼會分爲兩類:
1、頻繁執行的代碼(熱點代碼):會直接編譯成機器可以直接執行的二進制文件,同時保存起來,便於複用
2、不頻繁執行的代碼:通過解釋器執行
由上圖我們也能看出,java語言屬於編譯解釋型語言!其實:
解釋性或編譯性和語言本身是沒有關係的,即解釋性或編譯性可以看作是一種語言的狀態