【併發】JMM三大特性


JMM 是抽象的內存規範

對變量有改操作後,會把結果回寫回來。
,先用assign 把執行引擎的數據同步到工作內存中,然後從工作內存store出來,再用write到主內存中。
必須把它的工作內存的數據同步到主內存中
在這裏插入圖片描述


八大

java併發的三大特性:

  • 可見性
  • 原子性
  • 有序性

可見性

每個線程只能看到自己的工作內存的更改, 加一個volatile可以及時的看到,但是不加volatile線程在一定的時間之後也會看到,只是看到的時機確定不了。
volatile是java併發輕量級的鎖機制
線程B改了initFlag後就會主動通知線程A,讓線程A去主內存再拿一次
在這裏插入圖片描述


加了volatile後字節碼層面會給這個initFlag變量加一個ACC_VOLATILE標記
在這裏插入圖片描述

原子性

加了volatile也不能保證原子性,要用synchronized或者lock去保證原子性。

counter++ 相當於分了三步(讀、自加、寫回),這三步每一步是原子的,但是這三步加在一起不能保證原子性。因爲如果執行了一步就被切到另一個線程後,另一個線程對counter修改後因爲加了volatile會通知線程A 去主內存讀新的,那之前執行的就會扔掉 就少加了一次。
在這裏插入圖片描述

有序性

指令重排

我們的java代碼的順序 不是CPU執行指令的順序,他會進行指令重排比如a和b都依賴z變量 ,如果b指令是在很後面 就會被提前到和a指令一起加到緩存去
volatile可以解決指令重排

代碼證明確實有指令重排的情況

  • 第一種:x=0,y=1
    在這裏插入圖片描述

  • 第二種:x=1,y=0

在這裏插入圖片描述

  • 第三種 x=1,y=1
    在這裏插入圖片描述
  • 指令重排則會出現 x=0,y=0
    在這裏插入圖片描述

指令重排的危害

內存屏障

volatile 中加了內存屏障

我們也可以自己手動加內存屏障,用Unsafe類的以下三個方法:
在這裏插入圖片描述
在這裏插入圖片描述


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章