學習多執行緒的時候提到過java記憶體模型這個概念,說共享的變數都被分配到主記憶體中,不是應該是堆記憶體方法區嗎?混淆了應該去怎么理解。
之前一直理解的是堆疊記憶體修改了堆里面的共享變數, 現在學完多執行緒又多啦一個主記憶體和作業記憶體應該怎么理解。
uj5u.com熱心網友回復:
1)執行緒之間的共享變數存盤在主記憶體(Main Memory)中
2)每個執行緒都有一個私有的本地記憶體(Local Memory),本地記憶體是JMM的一個抽象概念,并不真實存在,它涵蓋了快取、寫緩沖區、暫存器以及其他的硬體和編譯器優化。本地記憶體中存盤了該執行緒以讀/寫共享變數的拷貝副本。
3)從更低的層次來說,主記憶體就是硬體的記憶體,而為了獲取更好的運行速度,虛擬機及硬體系統可能會讓作業記憶體優先存盤于暫存器和高速快取中。
4)Java記憶體模型中的執行緒的作業記憶體(working memory)是cpu的暫存器和高速快取的抽象描述。而JVM的靜態記憶體儲模型(JVM記憶體模型)只是一種對記憶體的物理劃分而已,它只局限在記憶體,而且只局限在JVM的記憶體。
這篇文章描述的比較清楚,可以參考看看 https://zhuanlan.zhihu.com/p/29881777
uj5u.com熱心網友回復:
首先,記憶體先分為靜態區和非靜態區,共享的變數,即被static修飾的變數或方法在靜態區,這個是jvm初始化加載類的時候就已經添加到記憶體里了,而非static修飾的變數或方法在沒有呼叫的時候,即沒有執行緒運行的時候,是不存在于記憶體中的,所以說靜態的變數或方法,優先于非靜態的變數或方法。其次,當有程式運行時,即創建了一個執行緒來處理某個請求時,會在非靜態區開辟一個空間出來,這個空間就叫作作業記憶體,屬于這個執行緒,有堆記憶體(存放物件),堆疊記憶體(存放變數),方法幀(非static修飾的方法),而共享變數jvm會創建一個副本給作業記憶體使用,但是非靜態區的方法里是可以修改靜態區里的共享變數的,等到該執行緒處理完請求,休眠或銷毀,會回寫該共享變數給靜態區,當下一個執行緒來處理的時候就會發現共享變數的值變了。
最后,我們經常說的多執行緒并發處理時,會導致共享變數的不可控,即資料不準確,假如說共享變數為1,A和B兩個執行緒幾乎同時過來請求,或者A還沒結束,B就過來請求了,獲得到的副本都是1,作業記憶體里都是1,然后A和B都做了減1的操作,然后回寫資料為0,但是其實應該是-1,因為減了兩次,所以一般對于共享變數都會加一個修飾符為volatile,同時對于修改共享變數的代碼進行加鎖處理,保證同時只能有一臺機器的一個執行緒去修改它。volatile修飾的共享變數的意義在于,當該共享變數發生變化時,jvm會通知各個作業記憶體,該共享變數已經變了,會把最新的值給各個作業記憶體。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/283493.html
標籤:Java SE
上一篇:關于自定義類加載器的問題
