【高性程】1.2線程安全之可見性問題

1.2.1線程安全之可見性問題

1.多線程中的問題

(1)所見非所得
(2)無法肉眼去檢測程序的準確性
(3)不同的運行平臺有不同的表現
(4)錯誤很難重現

2.問題

(1)從內存結構到內存模型

在這裏插入圖片描述

(2)工作內存緩存

在這裏插入圖片描述

(3)指令重排序

Java編程語言的語義允許編譯器和微處理器執行優化,這些優化可以與不正確的同步代碼交互,從而產生看似矛盾的行爲。(不僅僅是Java級別,也是CPU級別;
內存屏障,不僅會調用jit,還會調用CPU的指令禁止重排序)

3.內存模型的含義

內存模型描述程序的可能行爲。
在這裏插入圖片描述
【內存模型決定了線程在程序的每個點上可以讀取什麼值。】

4.Shared Variables共享變量描述

在這裏插入圖片描述

5.線程操作的定義

在這裏插入圖片描述
程序順序:如果一個程序沒有數據競爭,那麼程序的所有執行看起來都是順序一致的。
本規範只涉及到線程間(多線程)的操作。

6.對同步的規則定義(定義了讀數據)

在這裏插入圖片描述

7.happens-before先行發生原則

在這裏插入圖片描述
當程序包含兩個沒有被happens-before關係排序的衝突訪問時,就稱存在【數據爭用】。
遵守了這個原則,也就意味着有些代碼不能進行重排序,有些數據不能緩存。

8.volatile關鍵字

在這裏插入圖片描述

9.final在jvm中的處理

在這裏插入圖片描述

10.Word Tearing字節處理

在這裏插入圖片描述

11.double 和long的特殊處理

在這裏插入圖片描述
在這裏插入圖片描述

1.2.2線程安全概念之原子操作

編譯反編譯查看class內容的命令 :java -p -v 名稱
在這裏插入圖片描述

1.原子操作定義

在這裏插入圖片描述
【示例】
在這裏插入圖片描述
存在競態條件線程不安全,需要轉變爲原子操作才能安全。方式:循環CAS、鎖。

2.CAS機制

底層提供,針對變量級別,某一個屬性或者某一個內存地址的操作。
實際應用中,不需要這麼麻煩。因爲Java爲我們提供了一個J.U.C包內原子操作封裝類。
在這裏插入圖片描述
在這裏插入圖片描述
三個問題
在這裏插入圖片描述

3.J.U.C包內原子操作封裝類。

在這裏插入圖片描述
在這裏插入圖片描述

1.2.3鎖的概念和synchronized關鍵字

1.Java中鎖的概念

在這裏插入圖片描述
幾種重要的鎖實現方式:synchronized、 ReentrantLock、 ReentrantReadWriteLock

2.同步關鍵字synchronized

(1)概念

Java中每個對象都會有一個與之對應的監視器(object–mointor)
在這裏插入圖片描述
鎖消除:如果沒有什麼競爭,就不應該用鎖。
鎖粗化:如果存在多個小範圍的鎖,可以變成一個大的鎖。
同步關鍵字,不僅是實現同步,根據JVM規定還能保證可見性(讀取最新主內存數據,結束後寫入主內存)

(2)同步關鍵字加鎖原理

在這裏插入圖片描述

3.偏向鎖到輕量級鎖

在這裏插入圖片描述
在這裏插入圖片描述

4.重量級鎖-監視器(monitor)

修改mark word如果失敗,會自旋CAS一定次數,該次數可以通過參數配置:
超過次數,仍未搶到鎖,則鎖升級爲重量級鎖,進入阻塞。
monitor也叫做管程,計算機系統原理中有提及類似的概念。一個對象會有一個對應的monitor。
在這裏插入圖片描述

1.2.4Lock鎖接口實現

1.Lock的核心API

在這裏插入圖片描述
根據Lock的源碼註釋,Lock接口的實現,具備和同步關鍵字同樣的內語義。

2.RenentrantLock

獨享鎖;支持公平鎖、非公平鎖兩種模式;可重入鎖;
重入的時候,加鎖和解鎖的次數要一致;有多少次lock就需要有多少次unlock。
在這裏插入圖片描述

3.ReadWriteLock

在這裏插入圖片描述
在這裏插入圖片描述

4.Condition

在這裏插入圖片描述
在這裏插入圖片描述
源碼示例:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
synchronized要了解
lock 要學會使用

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