1. 程式人生 > >Java多執行緒中的記憶體模型

Java多執行緒中的記憶體模型

1)多執行緒執行下的記憶體模型:
JVM中規定了所有變數都儲存在主記憶體中,然後每條執行緒有自己的工作記憶體。
執行緒的工作記憶體中儲存了該執行緒需要用到的變數的拷貝值,執行緒在CPU上執行時都是對自己工作執行緒中的資料進行讀寫操作,
執行結束之後才把資料同步化主記憶體中。那麼資料一致性協議、資料一致性問題,JVM中就需要執行緒同步機制來達到多執行緒對同一記憶體區域的讀寫控制了。

此外,Java編譯器為了提高效能,採取了 指令重排序(類比計算機的 亂序執行),
若多個執行緒都有語句對同一記憶體區域進行操作的話,有可能因為指令重排序而導致結果不符預料。
因此,也需要執行緒同步機制來達到多執行緒對同一記憶體區域的讀寫控制。




2)主記憶體與工作記憶體的資料互動
JVM定義了8種操作來完成主記憶體與執行緒工作記憶體的資料互動:
       1:lock:把主記憶體變數標識為一條執行緒獨佔,此時不允許其他執行緒對此變數進行讀寫。
       2:unlock:解鎖一個主記憶體變數。
       3:read:把一個主記憶體變數值讀入到執行緒的工作記憶體,強調的是讀入這個過程。
       4:load:把read到變數值儲存到執行緒工作記憶體中作為變數副本,強調的是讀入的值的儲存過程。
       5:use:執行緒執行期間,把工作記憶體中的變數值傳給位元組碼執行引擎。
       6:assign(賦值):位元組碼執行引擎把運算結果傳回工作記憶體,賦值給工作記憶體中的結果變數。

       7:store:把工作記憶體中的變數值傳送到主記憶體,強調傳送的過程。
       8:write:把store傳送進來的變數值寫入主記憶體的變數中,強調儲存的過程。
JVM要求以上8個操作都具有原子性,即對資料的讀寫操作具有原子性。但也有例外,即:long、double的非原子性協定:這兩個64位型別的資料的讀、寫操作各需兩次進行,一次讀/寫 32 位,這兩次讀/兩次寫 是不保證原子性的。


3)原子性、可見性、有序性
原子性:基本資料型別的讀寫操作是原子性的;更大範圍的(程式碼塊)的原子性可以用lock、unlock操作來實現(上鎖後就只有 一個執行緒來執行了,所以不會被其他執行緒打斷原子操作),表現到程式碼層面就是使用syncrhoized同步塊。


可見性:當一個執行緒修改了被多執行緒共享的一個主記憶體變數值時,其他執行緒能立刻知道這個修改。
          我們在上面可以知道,JVM是通過工作記憶體中的變數值變化後,把新值同步會主記憶體,然後其他執行緒從主記憶體讀取這                個新值來實現可見性的。這裡有個區別:普通變數的值變化後,不一定會立刻同步會主記憶體,而是會等執行緒執行完或者             一段時間後才同步會,而且同步回主記憶體後,其他執行緒的工作記憶體也不一定會立刻讀取新值。而被volatile關鍵字修飾            的變數,一旦在工作記憶體中被修改,則立刻同步回主記憶體,並且其他使用了這個變數的執行緒的工作記憶體會立刻從主記憶體            讀取新值。而syncrhoized關鍵字修飾的變數由於一次只能有一個線程能使用,故一次也只能有一個工作執行緒讀寫它,            所以也能“縱向”地實現可見性。

有序性:多執行緒之間對共享資料的操作的有序性,可以通過volatile和syncrhoized關鍵字來保證。volatile關鍵字禁止了指令               重排序,而syncrhoized關鍵字規定了多個執行緒每次只能有一個執行緒對共享資料進行操作。


4)volatile關鍵字

一個volatile變數具有兩種特性:可見性、禁止指令重排序。但是,volatile不具備原子性!原因是volatile變數的值可以被多執行緒交替修改,而修改包括了read、load、use、store、write等過程,這些過程不能保證是原子執行的。
可見性:被volatile關鍵字修飾的變數,一旦在工作記憶體中被修改,則立刻同步回主記憶體,並且其他使用了這個變數的執行緒的工作內存會立刻從主記憶體讀取新值。


禁止指令重排序:volatile變數在賦值後會建立一個記憶體屏障:指令重排序時,位於後面的指令不能排到記憶體屏障之前。

相關推薦

java執行12.記憶體模型

假設一個執行緒為變數賦值:variable = 3;   記憶體模型需要解決一個問題:“在什麼條件下,讀取variable的執行緒將看到這個值為3?”   這看上去理所當然,但是如果缺少記憶體同步,那麼將會有許多因素使得執行緒無法立即甚至永遠,看到另一個執行緒的操作結果。 如:

Java執行記憶體模型(一):程序和執行基礎

Java多執行緒和記憶體模型(一) 由於java是執行在 JVM上 的,所以需要涉及到 JVM 的記憶體模型概念,需要理解記憶體模型,就需要多執行緒的基礎; 而執行緒是基於載體執行緒裡的,所以我們藉由作業系統的程序來講一講。 程序 什麼是程序?

Java執行記憶體模型

##目錄 - 多執行緒需要解決的問題 - 執行緒之間的通訊 - 執行緒之間的同步 - Java記憶體模型 - 記憶體間的互動操作 - 指令屏障 - happens-before規則 - 指令重排序 - 從源程式到位元組指令的重排序 - as-if-serial語義 - 程式順序

Java執行記憶體模型

1)多執行緒執行下的記憶體模型:JVM中規定了所有變數都儲存在主記憶體中,然後每條執行緒有自己的工作記憶體。執行緒的工作記憶體中儲存了該執行緒需要用到的變數的拷貝值,執行緒在CPU上執行時都是對自己工作執行緒中的資料進行讀寫操作,執行結束之後才把資料同步化主記憶體中。那麼資料一致性協議、資料一致性問題,JVM

Java執行以及記憶體模型的知識點梳理,有想到過這些嗎?

JMM大致描述: JMM描述了執行緒如何與記憶體進行互動。Java虛擬機器規範檢視定義一種Java記憶體模型,來遮蔽掉各種作業系統記憶體訪問的差異,以實現Java程式在各種平臺下都能達到一致的訪問效果。 JMM描述了JVM如何與計算機的記憶體進行互動 JMM都是圍繞著原子性,有序性和可見

Java執行Synchronized簡介和Static Synchronized的區別

在進行Java開發時,多執行緒的開發是經常會使用的。首先會問一個小問題啊,在Java中有幾種方法可以建立一個執行緒? 我給的答案是3種。(如果還有其他的請留言告訴我哈。) 1、建立直接繼承自Thread類建立執行緒子類。   步驟如下:a 定義一個子類,同時

細說Java 執行記憶體可見性

前言: 討論學習Java中的記憶體可見性、Java記憶體模型、指令重排序、as-if-serial語義等多執行緒中偏向底層的一些知識,以及synchronized和volatile實現記憶體可見性的原理和方法。 1、可見性介紹 可見性:一個執行緒對共用變數值的修改,能夠及時地被其他執行緒

java執行的異常處理

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

java執行顯式鎖的輪詢檢測策略

顯式鎖簡介 java5.0之前,在協調對共享物件的訪問時可以使用的機制只有synchronized和volatile,java5.0增加了一種新的機制:ReentrantLock。 鎖像synchronized同步塊一樣,是一種執行緒同步機制,與synchronized不同的是ReentrantLock提

Java執行注入Spring的Bean-使用靜態方法直接取的容器的spring物件

目前認為比較好的解決方案。 1,工具類 public class SpringApplicationContextHolder implements ApplicationContextAware { private static ApplicationContext context

Java執行與鎖模型-順序鎖與資源鎖

順序鎖:當應用程式使用2把以上的鎖時,就容易出現因為多執行緒獲取鎖的順序不同而死鎖的情形,包括交叉獲取應用程式範圍內的多把已知鎖、交叉獲取應用程式與第三方方法中的多把鎖而造成的順序死鎖。絕大多數死鎖都是因為CPU排程多執行緒時,在執行時序上是交叉進行的而造成亂序獲得多把鎖,從

白話理解java執行join()方法

join字面意思是加入,我理解為插隊. 舉例:媽媽在炒菜,發現沒喲醬油了,讓兒子去打醬油,兒子打完醬油,媽媽炒完菜,全家一起吃 package cn.yh.thread01; /** * *

java執行任務佇列模型

此篇文章將從任務佇列的設計;任務排程的方式(序列和並行)。程式碼很簡單,主要是設計的思想。 任務佇列 final class PendingPostQueue {     // 含有頭、尾指標的連結串列結構實現佇列     private PendingPost head;

Java執行volatile的場景應用

一、場景簡述 筆者在看多執行緒通訊相關問題時,不使用等待/通知機制實現多執行緒通訊的時候,發現b執行緒沒有與a執行緒發生正常通訊。 二、場景實現 如下是未發生正常通訊的程式碼 1、MyList類 package waitnotify; import java.ut

ArrayList在Java執行的應用

ArrayList是非執行緒安全的。 問題描述 開發中,存在這樣的業務邏輯,類似倒金字塔結構,下層資料需要基於上層的資料進行邏輯計算。設計思路是:定義一個全域性變數upLayerList,來儲存上一層的資料。每一層計算僅需要知道upLayerLi

Java執行start()和run()的區別

Java的執行緒是通過java.lang.Thread類來實現的。VM啟動時會有一個由主方法所定義的執行緒。可以通過建立Thread的例項來建立新的執行緒。每個執行緒都是通過某個特定Thread物件所對應的方法run()來完成其操作的,方法run()稱為執行緒體。通過呼叫Thread類的start(

java執行的sleep()、wait()、notify()和物件鎖的關係

1、sleep()不釋放物件鎖。 2、wait()釋放物件鎖。 3、notify()不釋放物件鎖。 (1)、notify釋放鎖嗎?不要誤導別人。notifty()只是喚醒此物件監視器上等待的單個執行緒,直到當前執行緒釋放此物件上的鎖,才有可能繼續執行被喚醒的執行緒。 (2)

JAVA執行join()方法的詳細分析

雖然關於討論執行緒join()方法的部落格已經非常極其特別多了,但是前幾天我有一個困惑卻沒有能夠得到詳細解釋,就是當系統中正在執行多個執行緒時,join()到底是暫停了哪些執行緒,大部分部落格給的例子看起來都像是t.join()方法會使所有執行緒都暫停並等待t的執行完畢。當然

Java執行的final和static

看Android的多執行緒發現其實是Java的多執行緒。我找了一本Java程式設計思想學習Java的併發機制。寫了一個demo,遇到一些問題,雖然最後想明白了,但是也暴露了我的Java基礎差勁的事實。之後我會通過寫部落格的方式來提高Java水平。現在說一下我的問

Java執行——生產者消費者模型-演義

這裡主要解讀(亂侃)生產者消費者模型的工作方式以及JDK5.0新增實現和傳統同步關鍵字實現方式的區別。 在JDK5.0新增了Lock、Condition這兩個介面來處理多執行緒安全問題。 Lock:可替代synchronized實現的同步函式或同步程式碼塊。 Conditi