Java內存模型,即 JMM (Java Memory Model),JMM 是一種規範,它規範了 JVM 運行的行爲,多線程操作對共享內存讀取時,所能讀取到的值應該遵守的規則。提供了一些解決可見性和有序性問題的方法例如 volatile、synchronized 和 final 三個關鍵字。
JMM爲程序中的所有操作定義了一定的規則,叫做Happens-Before 規則
Happens-Before 規則 解決了有序性和可見性的問題,如果你想保證你代碼執行順序不變(即有序性),你就需要遵守 Happens-Before 規則。要想保證操作A能看到操作B的結果,那麼A、B之間一定要滿足Happens-Before關係。happens-before並不是指操作A先於操作B發生,而是指操作A的結果在什麼情況下可以被後面操作B所獲取。
程序性順序規則
:一個線程中,如果程序中A操作在B操作之前,那麼線程中A操作將在B操作前執行。上鎖原則
:不同線程對同一個鎖的lock操作一定在unclock前。(先釋放鎖,纔可以加鎖,感覺也是廢話)volatile 變量原則
:volatile 修飾變量的寫操作,在讀操作之前,也就是先寫後讀(詳解看:volatile 關鍵字詳解)線程啓動原則
:線程A中啓動線程B,即線程A中調用了線程B的start() 方法,那麼start 操作在線程B其它操作之前。(感覺好像就是廢話)傳遞規則
:如果A早於B執行,B早於C執行,那麼A一定早於C執行。(好像也是廢話)線程中斷規則
:線程interrupt()方法的一定早於檢測到線程的中斷信號。線程終結規則
:如果線程A終結了,並且導致另外一個線程B中的ThreadA.join()方法取得返回,那麼線程A中所有的操作都早於線程B在ThreadA.join()之後的動作發生。(B 線程調用A線程,A線程操作都早於B線程的操作,好想也是廢話)對象終結規則
:一個對象初始化操作肯定先於它的finalize()方法。也就是說一個變量一旦被final 關鍵字修飾,且賦了初值,這個變量生下來就是不變的,即使怎麼優化,沒有任何影響。
總結
Happens-Before 是不是有一種因果關係的感覺。在現實世界裏,如果 A 事件是導致 B 事件的起因,那麼 A 事件一定是先於(Happens-Before)B 事件發生的,這個就是 Happens-Before 語義的現實理解。
Java 語言中,Happens-Before 的語義本質上是一種可見性,A Happens-Before B 意味着 A 事件對 B 事件來說是可見的,無論 A 事件和 B 事件是否發生在同一個線程裏。例如 A 操作發生在線程 1 上,B 操作發生在線程 2 上,Happens-Before 規則保證線程 2 上也能看到 A 事件的發生。happens-before並不是指操作A先於操作B發生,而是指操作A的結果在什麼情況下可以被後面操作B所獲取。