在討論以前必須先搞清四種存儲介質:寄存器、高級緩存、RAM和ROM。html
RAM與ROM你們都比較熟悉了,能夠當作是咱們常常說的內存與硬盤,寄存器屬於處理器裏面的一部分,而高級緩存cache是CPU設計者爲提升性能引入的一個緩存,也能夠說是屬於處理器的一部分。在利用CPU進行運算時一定涉及操做數的讀取,假如CPU直接讀取ROM,那麼這個讀取速度簡直是沒法忍受的,因而引入了內存RAM,這樣作確實讓速度提升了不少,但因爲CPU發展十分迅猛而另外一方面RAM的發展受到技術及成本的限制發展緩慢,此時產生了一個很難調和的矛盾,CPU運算速度比從RAM讀取數據的速度快了幾個數量級,木桶原理咱們都很熟悉了,桶的容量大小取決於最短的那塊,這必將影響處理器的效率,因而又引入了高級緩存,直接在CPU添加了幾個級別的緩存,他們的速度雖然沒法與寄存器比較,可是速度已經提高不少,基本能跟CPU的計算速度相匹配。總結成一句話就是,爲了解決CPU運算速度與讀取速度的矛盾,引入了多級存儲機制。java
如圖所示,機器的四種存儲介質是有關係的,通常程序運行時會將ROM相關的程序數據都讀進RAM中,而須要運算的數據或運算過程當中即將要用到的數據則會被讀進高速緩存或寄存器中,假如要進行的運算所須要的全部數據及指令都在寄存器和高速緩存中,則這個運算過程則表現得很是平坦,並不存在性能瓶頸,由於運算速度跟讀取速度基本匹配了。讀取速度快慢的排序以下:寄存器>cache>RAM>ROM,用一個比較好理解但不徹底正確的概念來解釋,由於寄存器是離CPU最近的,因此讀取最快,高速緩存次之,RAM第三,ROM離得最遠,天然速度最慢(固然不能徹底用距離來講明這個問題,但用距離是比較好理解的,另外的還由於這些存儲介質的硬件設計不一樣、工做方式不一樣)。從另外一個角度來看,CPU讀取數據的順序是先嚐試讀寄存器,若是不存在則嘗試讀高速緩存,若是還不存在則讀RAM,最後纔是讀ROM。一些CPU有三級cache,讀取時是一級一級往下直到找到須要的操做數,通常作的比較好的CPU3級緩存已經能讓命中率高達95%以上。緩存
有了上面的知識再往下探索就水到渠成了,若是把Java內存模型與多級存儲機制類比將發現爲了提升性能java引入了工做內存的概念,提升了線程執行時讀取數據的速度,這樣就能夠把java模型中的主存和工做內存分別於RAM和高速緩存或寄存器對應起來,每條線程的工做內存預先把須要的數據複製到高速緩存或寄存器(可是不保證全部的工做內存的變量副本都是放在高速緩存,也可能在RAM,具體的還要看JVM是如何實現的),這樣在多線程併發時性能獲得保證。固然寄存器和高速緩存因爲成本緣由存在容量大小限制的問題,這個也是考驗JVM實現的一個難題。bash
通常引入一種機制解決了一個問題,但同時也會帶來另一個問題,數據同步便是帶來的另外一個問題,便是否能保證當前運算使用的變量值老是當前時刻最新的值。若是變量值並不是最新值,將會致使數據的髒讀,最終可能致使計算結果截然不同。這時可能有人會想起java中有個volatile關鍵詞,毫無疑問它能保證可見性,讓每一個線程獲得的都是主存中最新的變量值,但它就足以保證數據的同步性了嗎?舉個典型例子,僞代碼以下:多線程
private volatile int count=0;
private void increase(){count++}
public static void main(String args){
建立30條線程執行;
每條線程任務都是執行10000次increase()方法;
}複製代碼
執行完全部線程任務,咱們指望的結果會是30*10000,但實際倒是一個小於30*10000的數,剛開始看到必定以爲有點奇怪,但仔細一想就清楚了,count++編譯後最終並不是一個原子操做,它由幾個指令一塊兒組合實現。下圖能較清晰地說明此點,在Java內存模型中,count++被分割成5個步驟(固然這個並非確切的指令執行步驟),這5步不具備原子性,假如在完成過程當中,其餘線程就去讀了主存的count變量,那明顯致使了一個髒讀現象。併發
致使這個問題的緣由實際上是由於volatile不具有鎖操做,要解決此問題其實不難,就是將這五步變爲原子操做,即保證線程一完成以前不能有其餘線程讀取count變量,對count變量加一個互斥鎖便可達到,線程一在執行第①步前對count加鎖,其餘線程沒法對count進行訪問,線程一執行完第⑤步後釋放鎖,此刻開始才容許其餘線程獲取此變量。性能
Volatile是一個很容易搞混的關鍵詞,不少經驗豐富的開發人員都不能正確使用它,這節從機器結構講到對應的java內存模型,再引出主存與工做內存之間數據同步的問題,進而更好地解釋了volatile的確切含義——它只保證可見性,它不足以保證數據的同步性。spa
========廣告時間========.net
鄙人的新書《Tomcat內核設計剖析》已經在京東銷售了,有須要的朋友能夠到 item.jd.com/12185360.ht… 進行預約。感謝各位朋友。線程
=========================
歡迎關注: