【Java 併發編程】 04 JMM內存模型解決有序性和可見性問題

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所獲取。

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