線程安全與鎖優化 1.線程安全 (1)當多個線程訪問一個對象時,如果不考慮這些線程在執行時環境下的調度和交替執行,也不需要進行額外的同步,或者在調用方進行任何其他的協調操作,調用這個對象的行為都可以獲得正確的結果,那麼這個對象時是線程安全的。 (2)Java語言中的線程安全 a)可以將Java語言中 ...
線程安全與鎖優化
1.線程安全
(1)當多個線程訪問一個對象時,如果不考慮這些線程在執行時環境下的調度和交替執行,也不需要進行額外的同步,或者在調用方進行任何其他的協調操作,調用這個對象的行為都可以獲得正確的結果,那麼這個對象時是線程安全的。
(2)Java語言中的線程安全
a)可以將Java語言中各種操作共用的數據分為5類:不可變,絕對線程安全,相對線程安全,線程相容和線程對立
b) 在Java語言中不可變的對象一定是線程安全的,無論是對象的方法實現還是方的調用者,都不需要再採用任何的線程安全保障措施。
c)線程相容:是指對象本身不是線程安全的,但是通過在調用端正確地使用同步手段來保證對象在併發環境中可以安全的使用。
d)線程對立:是指無論被調用端是否採取了同步措施,都無法在多線程環境中併發使用代碼。
(3)線程安全的實現方法
a)互斥同步是常見的一種併發正確性保障手段。同步是指在多線程併發訪問共用數據時,保證共用數據在同一時刻只能被一個線程使用。而互斥是實現同步的一種手段,臨界區、互斥量和信號量都是主要的互斥實現方式。
b)在Java中,最基本的互斥同步手段就是synchronized關鍵字,synchronized關鍵字經過編譯後,會在同步代碼塊的前後分別形成monitorenter和monitorexit這兩個位元組碼指令,這兩個位元組碼都需要一個reference類型的參數來指明要鎖定和解鎖的對象。
c)synchronized同步塊對同一線程來說是可重入的,不會出現自己把自己鎖死的問題。同步代碼塊在已進入的線程執行完之前,會阻塞後面其他線程的進入。
d)除了synchronized之外,還可以使用java.uitl.concurrent包中的重入鎖(ReentrantLock)來實現同步。
e)相比synchronized,ReentrantLock增加了一些高級功能:等待可中斷。可實現公平鎖,以及鎖可以綁定多個條件
等待可中斷:是指持有鎖的線程長期不釋放鎖的時候,正在等待的線程可以選擇放棄等待,改為處理其他事情,可中斷特性對處理執行時間非常長的同步塊很有幫助。
公平鎖:是指多個線程在等待一個鎖時,必須按照申請鎖的時間順序來依次獲得鎖
f)非阻塞同步:基於衝突檢測的樂觀併發策略,也就是說,先進行操作,如果沒有其他線程爭用共用數據,按操作就成功了;如果共用數據有爭用,產生了衝突,那就再採取其他的補償措施,這種樂觀的併發策略的許多實現都是不需要把線程掛起的。
g)無同步方案
可重入代碼:也叫純代碼,可以在代碼執行的任何時刻中斷它,轉而去執行另外一段代碼,而在控制權返回後,原來的程式不會出現任何錯誤。
線程本地存儲。
2.鎖優化
(1)自旋鎖與自適應自旋
為了讓線程等待,只需要讓線程執行一個忙迴圈(自旋),這項技術就是自旋鎖。
(2)鎖消除
指虛擬機即時編譯器在運行時,對一些代碼上要求同步,但是被檢測到不可能存在共用數據競爭的鎖進行消除。鎖消除的主要判定依據來源於逃逸分析的數據支持。
(3)鎖粗化
擴展(粗化)同步鎖的範圍
(4)輕量級鎖
(5)偏向鎖