簡單闡述JAVA記憶體模型中工作記憶體 拷貝 的理解

2021-06-29 04:27:59 字數 2290 閱讀 9345

mhttpclient = new defaulthttpclient(cm, params);然而,雖然解決了問題,但是引起了我們的思考,jmm裡面對執行緒的定義說:每個執行緒如果共享同乙個變數,則是把這個變數拷貝到自己的工作記憶體中去的,這也是jmm中所謂的不可見性,即執行緒是如何互動的,那麼,結合以上應用來看,這樣的理論不是有悖我們的實踐結果嗎?兩個執行緒同時拷貝httpclient到自己的本地記憶體中嗎?互不影響吧?怎麼相互衝突呢?

這是一下的執行緒方法run(),在方法體中呼叫乙個類的靜態方法,這個靜態方法就是使用httpclient請求伺服器。

public void run()

public int getid()

public static string requestsever()
這個類怎麼拷貝到工作記憶體中去的呢?其實也很簡單:在底層,就是乙個結構體,我們直接複製這個結構體就好,比如,這個結構體其實大小應該是20個位元組(包括虛表指標一起),加上整形,字串的位址值,8位元組的浮點,直接把這些數值拷貝到自己的工作記憶體上去。那你還要問?那之中的方法呢?注意:方法是**段:這裡的方法分為非靜態方法和靜態方法。

這裡一定要搞清楚靜態方法和非靜態方法的理解:

靜態方法有乙個隱含的傳入引數,該引數是jvm給它的,和我們怎麼寫**無關,

這個隱含的引數就是物件例項在stack中的位址指標。因此非靜態方法(在stack中的指令**)總是可以找到自己的專用資料(在heap 中的物件屬性值)。

當然非靜態方法也必須獲得該隱含引數,因此非靜態方法在呼叫前,必須先new乙個物件例項,獲得stack中的位址指標,否則jvm將無法將隱含引數傳給非靜態方法。

而靜態方法無此隱含引數,因此也不需要new物件,只要class檔案被classloader load進入jvm的stack,該靜態方法即可被呼叫。

當然此時靜態方法是訪問不到heap 中的物件屬性的。

所以,非靜態方法的**是在棧上的,所以,這裡不會拷貝方法的**段到執行緒的主存中去,而是需要用到這個方法時候,根據student 類new出的引用變數尋找其方法在記憶體中的位址中的位址值來尋找其**段的位址值,然後在根據執行緒的程式計數器pc來執行**指令。所以說,這裡的非靜態方法不會被拷貝,而是在執行的時候,直接根據位址值找到的。

靜態方法呢?靜態屬性是儲存在stack中的(基本型別儲存在stack中,物件型別位址儲存在stack,值儲存在heap 中),所以,上述的 public

static string requestsever()這個靜態方法,也是全域性共享的。

所以,靜態方法體也不會被拷貝到執行緒的工作記憶體中去。

那麼,如果上述的student的類,裡面有乙個類型別的變數(引用)呢?而在多執行緒中又是如何的呢?比如這樣:

class student

「` 這樣的型別要怎麼分析呢?還是一樣的,執行緒拷貝結構體,只是這個結構體都是位址值而已,那麼訪問的時候,對,也就說,我們只是拷貝了位址值,而不是把記憶體的堆空間上的位址值拷貝過來了,因此,如果多執行緒都共享了乙個student的類變數,那麼訪問array或者mteacher這個變數的時候,是直接去記憶體的堆空間中定址的!

這樣一來,我們終於把jmm中」拷貝」理解通透了,拷貝一些什麼東西,哪些才是可以拷貝的,(**是執行緒共享的)。

用以上理論來解釋這個模型,就可以了,兩個執行緒共享了httputils類中的乙個靜態方法,也就是說,兩個執行緒其實都沒有拷貝變數的到自己工作記憶體中去,因為靜態的**是全域性共享的,自然不會被拷貝,而靜態的方法裡面,httpclient也是靜態的,所以,兩個執行緒共享了乙個位址值,按照這個位址值去記憶體上定址,自然會產生多執行緒衝突啦。

java記憶體模型

一 原子性 原子性是指乙個操作是不可中斷的,即使是多個執行緒一起執行的時候,乙個操作的開始,就不會被其他執行緒干擾 那麼有人會想到 i 是原子操作嗎?答案肯定不是。因為i 至少包含兩個操作,讀 從記憶體中讀出來 和行為 加上去 還有可能把加完後的資料在方法到i裡面去,出來也是1,這兩個執行緒同時進行...

Java記憶體模型

1.首先,執行緒a把本地記憶體a中更新過的共享變數重新整理到主記憶體中去。2.然後,執行緒b到主記憶體中去讀取執行緒a之前已更新過的共享變數。1.共享物件對各個執行緒的可見性 2.共享物件的競爭現象 指令級並行的重排序 如果不存l在資料依賴性,處理器可以改變語句對應機器指令的執行順序。記憶體系統的重...

Java記憶體模型

int x 0 thread a int y x thread bint x 5 int y 8 int z x y 關於上面的 存在這樣關係 x和z之間存在資料依賴關係,同時y和z之間也存在資料依賴關係。為了得到正確的結果,執行指令序列時,z不能重排序到x和y的前面。但是x和y之間並沒有資料依賴關...