Java多線程內存模型
1.併發線程間的通信機制有兩種: 共享內存和消息傳遞
a.共享內存和消息傳遞的區別:
共享內存:線程間有公共狀態,通過讀寫內存中的公共狀態隱式通信
消息傳遞:線程間沒有功能狀態,線程間通過發送消息顯示通信
Java線程使用的是共享內存的方式實現線程通信
2.線程內存可見性數據(結合JVM內存結構)
a.所有實例域、靜態域、數組元素存儲的堆中,會有可見性問題
b.局部變量、方法參數和異常處理器參數,生命週期與線程同步,沒有可見性問題
volatile修飾成員變量的作用: 改變變量,同步刷新到共享內存中,保證了內存的可見性
synchorized修飾的方法或代碼塊,確保多線程在併發同一刻,只有一個線程處於方法或代碼塊中,確保線程訪問的可見性和排他性
3.JAVA線程內存模型(線程——工作內存——主內存)
線程之前的共享變量存儲在主內存中,每個線程有一個私有的本地內存(工作內存),本地內存(工作內存)存儲的是該線程以讀寫的共享變量副本
4.JAVA線程重排序: 執行程序時,編譯器和處理器常常會對指令做重排序
a.編譯器優化重排序:編譯器在不改變單線程語義的前提下,可以重新安排語句的執行順序
b.指令級並行重排序:屬於處理器重排序——現代處理器通過指令級並行技術,來將多條指令重疊執行
c.內存系統的重排序:屬於處理器重排序——處理器使用緩存和讀寫緩衝區
編譯器可以通過內存屏障,禁止特定的處理器重排序
5、Java處理多線程內存語義(volatile,final,鎖)
兩大特性: 可見性、原子性和有序性
可見性:讀取一個變量的值,可以立即看到其他線程對此變量的修改
原子性: 一個操作是不可中斷的。一個線程執行操作,不受其他線程的干擾
有序性: 指令重排,線程執行順序。指令重排可以保證串行語義一致,不能保證多線程併發語義一致
a. volatile的運行原理
volatile處理線程併發的時候,具有可見性,也具有不完整的原子性(缺點:對於num++這種複合型操作,不具有原子性)——可以用current包下的原子類進行替換
volatile的內存語義:
讀的內存語義:當讀一個volatile變量時,JMM會將該線程的本地變量設置爲無效,將從主內存中獲取到共享變量
寫的內存語義:當寫一個volatile變量時,JMM會將該線程的本地內存中的共享變量刷新到主內存中
b.鎖的工作原理
鎖的內存語義:
釋放的內存語義:當線程釋放鎖時,JMM會將該線程的本地內存中的共享變量刷新到主內存中
獲取鎖的內存語義:當線程獲取鎖時,JMM會將該線程的本地內存設置爲無效,從而使被監聽器保護的臨界區代碼必須從主內存中讀取共享變量