1. 不可變:
不可變的物件一定是執行緒安全的。如string類。
2. 絕對執行緒安全
3. 相對執行緒安全
4. 執行緒相容
5. 執行緒對立
1. 互斥同步(阻塞式同步)
1) 同步指的是:多個執行緒併發訪問共享資料時,保證共享資料在同一時刻只能被乙個執行緒使用。
2) 互斥指的是:同步的手段。如:臨界區、互斥量和訊號量。
3) 最基本的同步互斥手段:synchronized關鍵字。
a) 原理:synchronized關鍵字經過編譯後,會在同步**塊前後分別形成monitorenter和monitorexit這兩個位元組碼指令。
b) 在執行monitorenter指令時,首先要嘗試獲取物件鎖。若這個物件沒被設定鎖,或已經擁有了這個物件鎖,把鎖的計數器+1。
c) 相應的執行monitorexit指令時,鎖計數器-1,當為0時釋放鎖。
d) 若獲得物件失敗則阻塞當前執行緒。
4) 另一種手段:reentrantlock來實現
reentrantlock增加的新功能:
a) 等待中斷:當持有鎖的執行緒長期不釋放鎖的時候,正在等待的執行緒可以選擇放棄等待。
b) 公平鎖:可以講多個執行緒在等待同乙個鎖時,必須按照申請鎖的時間順序依次獲得鎖。
c) 鎖繫結多個條件:乙個reentranlock物件可以同時繫結多個condition物件。
5) 兩種方式的比較:
a) 在jdk1.6之前在多執行緒環境中synchronized的吞吐量下降的嚴重,但reentranlock效能幾乎不變。
b) 在jdk1.6之後二者效能基本上持平。
c) 應該優先考慮使用synchronized來同步。
2. 非阻塞同步
1) 互斥同步屬於一種悲觀的併發策略。即總認為不去做同步措施就一定會出現問題,故無論共享資料是否真的會出現競爭,都要加鎖。
2) 非執行緒阻塞:是基於衝突檢測的樂觀併發控制策略。即先操作,如果沒有其它執行緒徵用共享資料,則成功。如果共享資料有徵用,採取補償措施。(不斷的重試,直到成功)
3. 無同步方案
如果方法中不涉及共享資料,那它自然無須任何同步措施去保證正確性。
1) 可重入**
可重入的**都是執行緒安全的,但並非所有的執行緒安全的**都是可重入的。
2) 執行緒本地儲存
鎖優化技術:適應性自旋、鎖消除、鎖粗化、輕量級鎖和偏向鎖。
1. 自旋鎖:當兩個或兩個以上的執行緒同時並行執行,讓後面請求鎖的那個執行緒「稍等一下」,但不放棄處理器的執行時間,看看持有所的執行緒是否能很快釋放鎖。
2. 缺點:自旋的執行緒只會白白消耗處理器資源,帶來效能上的浪費。故需要使等待時間有一定的限度
3. 改進:等待時間要自適應。等待時間隨著程式執行和效能監控資訊的不斷完善。
1. 鎖消除:虛擬機器及時編譯器在執行時,對一些**上要求同步,但是被檢測到不可能存在共享資料競爭的鎖進行消除。
2. 判斷依據:源於逃逸分析的資料支援。若堆上的所有資料都不會逃逸出去從而被其他執行緒訪問到,那就可以吧它們當作棧上的資料看待。
1. 上面出現的問題:如果一系列的連續操作都對同乙個物件反覆加鎖和解鎖,甚至加鎖操作是出現在迴圈體中,那即使沒有執行緒競爭,頻繁地進行互斥同步操作也會導致不必要的效能損耗。
2. 措施:如果虛擬機器探測到有這樣一串零碎的操作都對同乙個物件加鎖,【將會把加鎖同步的範圍擴充套件到整個操作序列外部】。
1. 加鎖過程:
1) **進入到同步**塊的時候,如果此同步物件沒有被鎖定,將會在當前執行緒的棧幀中建立乙個名為鎖記錄(lock record)空間,用來儲存物件目前的頭資料。
2) 將物件的頭記錄更新為指向lock record的指標。
a) 更新成功:那麼這個執行緒就擁有了該物件的鎖
b) 失敗:檢查物件的物件頭是否指向當前執行緒的棧幀。
a) 是:說明當前執行緒已經擁有這個物件的鎖,直接進入同步塊中執行。
b) 否:說明這個鎖物件已經被其他執行緒搶占。
3) 如果兩條以上執行緒徵用同乙個鎖,那輕量級鎖失效。
2. 解鎖過程:
1) 若物件的物件頭仍然指向現成的鎖記錄,則把物件當前的mark word和執行緒中副本替換回來。
a) 成功:整個同步過程完成
b) 失敗:說明其他執行緒嘗試獲取該鎖,那就要釋放鎖的同時喚醒被掛起的執行緒。
1. 與輕量級鎖的區別:
輕量級鎖:是在無競爭情況下,消除同步使用的互斥量。
偏向鎖:在無競爭情況下把整個同步都消除掉。
2. 加鎖過程:
1) 當鎖物件第一次被執行緒獲取的時候,虛擬機器包物件頭中的標記為設為「01」。
2) 把獲取到這個鎖的執行緒的id記錄在物件的mark word之中。
3. 解鎖過程:
1) 當有另外乙個執行緒去嘗試獲取這個鎖時,偏向模式宣告結束。
2) 根據鎖物件目前是否處於被鎖定的狀態,撤銷偏向後恢復到「01」或「00」。
4. 優點:
提高帶有同步但競爭的程式效能。
一夜搞懂 JVM 執行緒安全與鎖優化
我的 github 部落格 之前我們學習了記憶體模型和執行緒,了解了jmm和執行緒,初步 了jvm怎麼實現併發,而本篇文章,我們的關注點是jvm如何實現高效 併發程式設計的目的是為了讓程式執行得更快,提高程式的響應速度,雖然我們希望通過多執行緒執行任務讓程式執行得更快,但是同時也會面臨非常多的挑戰,...
JVM學習 (九)執行緒安全和鎖優化
從以前流行的面向過程程式設計到現在的物件導向程式設計,物件導向程式設計極大的提公升了現代軟體開發的效率和規模,但是不可避免的是物件之間的相互切換,為了讓程式維護的更好更好,我們必須引入 高效併發 來保證併發的正確性 安全性和效率性。比較寬泛的定義 沒有什麼可以操作性 如果乙個物件可以被多個執行緒同時...
執行緒安全與鎖優化
樂觀鎖 cas aba 版本號 atomicstampedreference 時間戳atomicmarkablereference boolean 可重入 絕對執行緒安全,不依賴共享資料 使用引數,區域性變數 自旋鎖 認為鎖很快釋放,占用cpu迴圈獲取鎖,超過一定次數 時間 再掛起執行緒,自旋次數上...