首先,這二者是徹底不一樣的概念,絕對不能混爲一談。
1.什麼是Java內存模型?
Java內存模型是Java語言在多線程併發狀況下對於共享變量讀寫(實際是共享變量對應的內存操做)的規範,主要是爲了解決多線程可見性、原子性的問題,解決共享變量的多線程操做衝突問題。編程
多線程編程的廣泛問題是:緩存
- 所見非所得
- 沒法肉眼檢測程序的準確性
- 不一樣的運行平臺表現不一樣
- 錯誤很難復現
故JVM規範規定了Java虛擬機對多線程內存操做的一些規則,主要集中體如今volatile和synchronized這兩個關鍵字。數據結構
- volatile 是JVM提供的對共享變量在多線程讀寫時的可見性保證,主要做用是對volatile修飾的共享變量禁止被緩存(這裏跟CPU的高速緩存和緩存一致性協議有關),不作重排序(重排序:在CPU處理速度遠大於內存讀寫速度的現狀下爲了提升性能而進行的優化),可是並不保證共享變量操做的原子性。
- synchronized 是JVM提供的鎖機制,經過鎖的特性和內存屏障保證鎖住區域操做的原子性、可見性、有序性。
- 鎖爭搶的是對象(static鎖的是類對象,非static鎖的是當前對象,即this,鎖方法塊鎖的是自定義對象)在堆內存中對象頭的一塊內存的「主權」,只有一個線程能獲取該「主權」,即排他性,經過鎖的排他性保證對鎖住區域的操做的原子性
- 經過在代碼先後加入加載屏障(Load Barrier)和存儲屏障(Store Barrier),能保證鎖住代碼塊或者方法中對共享變量的操做的可見性
- 經過在代碼先後加入獲取屏障(Acquire Barrier)和釋放屏障(Release Barrier),能保證鎖住代碼塊或者方法中對共享變量的操做的有序性
2.什麼是JVM運行時數據區?
JVM運行時數據區,是Java虛擬機在運行時對該Java進程佔用的內存進行的一種邏輯上的劃分,包括方法區、堆內存、虛擬機棧、本地方法棧、程序計數器。這些區塊實際都是Java進程在Java虛擬機的運做下經過不一樣數據結構來對申請到的內存進行不一樣使用。多線程
- 方法區:JVM用來存儲加載的類信息、常量、靜態變量、編譯後的代碼等數據。不一樣虛擬機有不一樣的實現,oracle的HotSpot在Java7中方法區放在永久代,Java8中方法區放在元空間,並經過GC機制來管理。
- 虛擬機棧:每一個線程私有的空間,由多個棧幀組成,一個方法對應一個棧幀,棧幀包括局部變量表、操做數棧、動態連接、方法返回地址、附加信息等。棧內存默認最大1M,超出跑出StackOverFlowError。
- 本地方法棧:相似虛擬機棧,是爲虛擬機使用native本地方法而準備的。具體實現由虛擬機廠商來實現。HotSpot虛擬機中實現與虛擬機棧一致,同時超出大小拋StackOverFlowError。
- 程序計數器:記錄當前線程執行字節碼的位置,存儲的是字節碼指令地址,若是native方法,則爲空。CPU同一時間只能執行一條線程中的指令,線程切換後經過程序計數器來恢復正確的執行位置。
- 堆內存:全部線程均可以訪問修改,存放的是對象實例,是數據區中佔用空間最大的部分,在HotSpot虛擬機中分爲新生代和老年代,新生代又分爲Eden區和Survivor0區、Survivor1區。