1. 程式人生 > >JVM——執行緒安全的實現方法

JVM——執行緒安全的實現方法

一互斥同步(悲觀的併發策略)

同步是指在多個執行緒併發訪問共享資料時,保證共享資料在同一時刻只被一個執行緒使用。互斥是實現同步的一種手段,下面介紹兩種互斥同步的手段:synchronized關鍵字和concurrent包中的重入鎖ReentrantLock

synchronized關鍵字:

synchronized關鍵字經過編譯之後,會在同步塊的前後分別形成monitorenter和monitorexit兩個位元組碼指令,這兩個位元組碼都需要一個reference型別的引數來指明要鎖定和解鎖的物件。如果Java程式中的synchronized明確指定了物件引數,那就是這個物件的reference,如果沒有明確執行,根據synchronized修飾的是例項方法還是類方法,去取對應的例項物件或Class物件作為鎖物件。

ps:synchronized同步塊對同一條執行緒來說是可重入的,(鎖是可以重入的)

同步塊在已進入的執行緒執行完之間,會阻塞後面的其他執行緒進入。

ReentrantLock:

相比synchronized,ReentrantLock增加了一些高階功能:

  1. 等待可中斷是指當持有所的執行緒長期不釋放鎖的時候,正在等待的執行緒可以選擇放棄等待,改為處理其他事情,可中斷性對處理執行時間非常長的同步塊很有幫助
  2. 公平鎖是指在多個執行緒在等待同一個鎖時,必須按照申請鎖的時間順序來依次獲得鎖。
  3. 鎖繫結多個條件是指一個ReentrantLock物件可以同時繫結多個Condition物件,而在synchronized中只能實現一個條件

總結:在synchronized能實現需求的情況下,優先考慮使用synchronized進行同步

二非阻塞同步(樂觀的併發策略)

基於衝突檢測的樂觀的併發策略,先進行操作,如果沒有其他執行緒爭用共享資料,那操作就成功了;如果共享資料由爭用,產生了衝突,那就再採取其他的補償措施

一般靠硬體來實現操作和衝突檢測這兩個步驟具有原子性,常用的指令:CAS

三無同步方案

可重入程式碼:這種程式碼也叫做春程式碼,可以在程式碼執行的任何時刻中斷它,轉而去執行另外一段程式碼,而在控制權返回後,原來的程式不會出現任何錯誤。相對於執行緒安全來說,可重入性是更基本的特性,它可以保證執行緒安全,即所有的可重入程式碼都是執行緒安全的,但是並非所有的執行緒安全的程式碼都是可重入的。

執行緒本地儲存:如果一段程式碼中所需要的資料必須與其他程式碼共享,那就看看這些共享資料的程式碼能否在同一個執行緒中執行?如果能保證,我們就可以把共享資料的可見範圍限制在同一個執行緒之內,這樣無需同步也能保證執行緒之間不出現資料爭用的問題。

總結:

Java語言中,如果一個變數要被多個執行緒訪問,可以使用volatile關鍵字宣告它為“易變的”;如果一個變數要被某個執行緒獨享,可以通過java.lang.ThreadLocal類來實現執行緒本地儲存的功能。