JAVA併發鎖 - 悲觀鎖VS樂觀鎖(一)
文章目錄
在討論鎖相關概念和原理之前,我們先來了解一下執行緒安全的問題,執行緒安全主要有以下兩方面影響:
1.操作中存在臨界資源,也稱共享資源。
2.系統中存在多執行緒操作臨界資源。
常見的解決方案:
當系統中存在多個執行緒操作臨界資源時,我們需要保證執行緒之間的共享資源可見,當其中一個執行緒獲取到操作共享資源的權利後,會對該資源進行加鎖限制,防止其它執行緒再對該資源進行修改,當該執行緒操作完後,會釋放資源鎖。
悲觀鎖VS樂觀鎖
在併發操作中,為了實現執行緒之間的資源共享,保證資料的一致性,通常需要進行執行緒間資料同步,在java中同步有很多種方式,其中 synchronized 是最常見的一種實現資源同步的方式,對資源進行加鎖。接下來我們首先研究下 悲觀鎖和樂觀鎖。簡單總結如下圖所示:
1.悲觀鎖
1.1什麼是悲觀鎖
悲觀鎖:執行緒進行併發操作時,總是以最壞的情況進行操作,假設總有其它執行緒會對資源進行更新,所以,當執行緒獲取到資源時,會對資源進行加鎖操作,避免其它執行緒對資源進行更新,等待當前執行緒操作完後,會釋放鎖,此時其它執行緒可以獲取資源,並完成相應的操作。
1.2原始碼分析
synchronized
synchronized 關鍵字在java中使用很頻繁,使用該關鍵字可以資源進行加鎖,本質上採用搶佔式獲取鎖的機制,是一種典型的悲觀鎖。synchronized 也是一種互斥鎖。關於互斥鎖將在後續文章中做出說明。
- 三種應用方式
例項方法塊
靜態方法塊
程式碼塊
- 底層原理
- java虛擬機器對synchronized的優化
- 關注點
Lock
1.3應用場景
悲觀鎖應用場景:
併發訪問中存在頻繁更新資料操作。
1.4實現
2樂觀鎖
2.1什麼是樂觀鎖
樂觀鎖:執行緒進行併發操作時,總是以最好的情況進行操作,假設沒有其它執行緒會對資源進行操作,如果當前執行緒只是進行查詢操作,那麼獲取到當前最新的資料返回給介面即可,【至於這個共享資源在獲取過程中會被其它執行緒更改,獲取到的資源可能不是最新的,導致出現這個問題應該歸於其它執行緒更新共享資源的一種機制】。如果當前執行緒需要對共享資源進行更新操作,那麼常常會採用一種校對更換的機制,即 CAS(Compare And Swap)。CAS原理將在下面進行介紹。
2.2原始碼分析
CAS 原理
cas是一種無鎖機制,在不使用鎖的情況下實現多執行緒之間的資源共享,cas中有三個值:需要讀寫的記憶體值V,需要進行比較的值A,需要更新的值B(需要寫入記憶體)。
當且僅當V == A時,才會進行更新操作V=B(將V值替換為B),更新操作是一個不斷重試的機制,如果不滿足V==A,會一直重試,直到滿足後作更新操作。
CAS 問題
- ABA問題
- 更新重試操作耗資源
- 只能對一個變數作原子操作
2.3應用場景
併發訪問中存在頻繁查詢資料操作
2.4實現
總結
悲觀鎖是一種搶佔式鎖,獲取資源後,對資源進行加鎖,保證只有當前執行緒可進行操作,其它執行緒繼續阻塞,等待當前執行緒處理完釋放鎖後,才可進行資源爭奪。悲觀鎖適合於頻繁更新的操作,比如資料庫更新時表鎖等。
樂觀鎖實際上並未對共享資源進行加鎖,而是採用比較更新的(cas)機制,保證多執行緒之間共享資源的一致性。更新操作是一個不斷重試的操作。樂觀鎖適合於頻繁查詢的操作。
未完待續…