JMM
請你談談對Volatile的理解
Volatile是jvm提供的輕量級的同步機制(和synchronized差不多,但是沒有synchronized那么強大)
- 保證可見性
- 不保證原子性
- 禁止指令重排
什么是JMM
JMM:java內存模型,不存在的東西,概念!約定!
JMM即為JAVA 內存模型(java memory model)。因為在不同的硬件生產商和不同的操作系統下,內存的訪問邏輯有一定的差異,結果就是當你的代碼在某個系統環境下運行良好,并且線程安全,但是換了個系統就出現各種問題。Java內存模型,就是為了屏蔽系統和硬件的差異,讓一套代碼在不同平臺下能到達相同的訪問結果。JMM從java 5開始的JSR-133發布后,已經成熟和完善起來。
關于JMM的一些同步的約定:
- 線程解鎖前,必須把共享變量
立刻
刷回主存。
主內存中有一個共享變量,假設線程a要操作主內存中的共享變量,它不會直接操作主內存中的共享變量,而是會拷貝一份到線程a的工作內存中,如果線程a修改了自己線程內存中的共享變量,那么在解鎖前需要把更新的共享變量的值賦值給主內存中的共享變量。 - 線程加鎖前,必須主存中的最新值到工作內存中。
- 加鎖和解鎖是同一把鎖。
線程、工作內存、主內存
-
從主存中read變量,load到線程的工作內存中,變量就被加載到了線程的工作內存中
-
執行引擎Use變量,并assign(返回)。
-
將工作內存中的變量write并store到主內存中。
-
lock和unlock
意思就是線程a執行的慢,變量還沒有及時刷新到主存中,線程b就已經更改變量并刷新到了主存中,此時線程a依舊拿著舊的變量,這就出現了問題。
內存交互操作有8種,虛擬機實現必須保證每一個操作都是原子的,不可在分的(對于double和long類型的變量來說,load、store、read和write操作在某些平臺上允許例外)
- lock (鎖定):作用于主內存的變量,把一個變量標識為線程獨占狀態
- unlock (解鎖):作用于主內存的變量,它把一個處于鎖定狀態的變量釋放出來,釋放后的變量才可以被其他線程鎖定
- read (讀取):作用于主內存變量,它把一個變量的值從主內存傳輸到線程的工作內存中,以便隨后的load動作使用
- load (載入):作用于工作內存的變量,它把read操作從主存中變量放入工作內存中
- use (使用):作用于工作內存中的變量,它把工作內存中的變量傳輸給執行引擎,每當虛擬機遇到一個需要使用到變量的值,就會使用到這個指令
- assign (賦值):作用于工作內存中的變量,它把一個從執行引擎中接受到的值放入工作內存的變量副本中
- store (存儲):作用于主內存中的變量,它把一個從工作內存中一個變量的值傳送到主內存中,以便后續的write使用
- write (寫入):作用于主內存中的變量,它把store操作從工作內存中得到的變量的值放入主內存的變量中
JMM對這八種指令的使用,制定了如下規則:
-
不允許read和load、store和write操作之一單獨出現。即使用了read必須load,使用了store必須write
-
不允許線程丟棄他最近的assign操作,即工作變量的數據改變了之后,必須告知主存
-
不允許一個線程將沒有assign的數據從工作內存同步回主內存
-
一個新的變量必須在主內存中誕生,不允許工作內存直接使用一個未被初始化的變量。就是對變量實施use、store操作之前,必須經過assign和load操作
-
一個變量同一時間只有一個線程能對其進行lock。多次lock后,必須執行相同次數的unlock才能解鎖
-
如果對一個變量進行lock操作,會清空所有工作內存中此變量的值,在執行引擎使用這個變量前,必須重新load或assign操作初始化變量的值
-
如果一個變量沒有被lock,就不能對其進行unlock操作。也不能unlock一個被其他線程鎖住的變量
-
對一個變量進行unlock操作之前,必須把此變量同步回主內存
部分內容轉載自:
https://www.cnblogs.com/null-qige/p/9481900.html
華為員工中患憂郁癥、焦慮癥的不斷增多,令人十分擔心。有什么辦法可以讓員工積極、開放、正派地面對人生?我思考再三,不得其解。
任正非:要快樂地度過充滿困難的一生