洪水和暴雨褪去,酷暑如期而來,酷暑侵蝕着整個上海的天氣。燥熱的天氣讓想跳槽的心更加躍躍欲試,重新翻翻了周老板的《深入理解Java虛擬機》把自己對voliate的理解重新梳理一下也記錄一下。
現代的計算器多任務處理是一項必須的功能,許多場景下需要計算器同時去處理多件事,這不僅僅是應為計算器的運算能力太強大了,更多的原因是應為計算器的運算速度與它存儲和通信子系統的速度差距太大,大量的時間都花費在磁盤I/O、網絡通信或者數據庫訪問上,這時我們不希望處理器大部分時間都處於等待狀態,這時多任務就應運而生。處理器在執行任務的時候需要與內存交互、如讀取數據、存儲運算結果,。由於計算器的存儲設備和處理器的運算速度有着幾個數量級的差距,所以現代計算機系統中都加入一層或者多層讀寫速度與處理器運算速度接近的高速緩存來作為內存與處理器之間的緩沖,將運算需要使用的數據復制到緩沖中,讓運算快速進行,當運算完成后再從緩存同步到內存中,這樣處理器就無須等待緩慢的內存讀寫了。高速緩存解決了處理內存速度之間的矛盾也帶來了新問題:緩存一致性
java的內存模型所以的變量都存在主存中(虛擬機內存的一部分可以與物理主存類比)。每條線程都有自己的工作內存,可以與處理器的高速緩存類比,工作線程就是保存了被該線程使用中變量的主內存副本。,線程對變量所有逇讀寫都是在工作內存中進行的,線程之間的變量值傳遞也都需要通過主存傳遞。工作內存在完成計算后會將值寫會主存中。好說了這么多(抄了這么多) 我們大概了解了處理器是如何工作的了。
voliate特性
現在我們開始進入正題關於voliate關鍵字,voliate關鍵字可以說是java輕量級的同步機制。當一個變量定義為voliate后,他將具有兩個特性:
第一項保證此變量對所有的線程的可見性,這里的可見性主要是每當線程改變了這個值會在第一時間刷新到主存中去其他線程會在第一時間讀取到新值。但是由於每次使用前都要刷新一次,執行引擎得到的一定是最新的,但是java運算符操作是非原子性的因此voliate在並發的情況下運算一樣是不安全的。
第二項使用voliate變量是禁止指令重排序優化,普通變量會保證該方法的執行過程所有依賴賦值結果的地方都能獲取到正確的結果,而不能保證變量賦值操作的順序和代碼中執行順序一致。比如在指令重排序的優化可能會把代碼后面一些的賦值操作優化到前面進行。而加入了voliate關鍵字相當於增加了一個內存屏障指令重排序的時候不能把后面的指令重排序到內存屏障之前的位置。
voliate可以說是java輕量級的同步機制的同步機制,他的讀取性能幾乎與普通變量沒有什么區別,但是寫操作可能會慢上yuixie,因為他需要本地代碼中插入需要內存屏障的指令保證處理器不會亂序執行。
參考《深入理解Java虛擬機》
