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)機制,保證多線程之間共享資源的一致性。更新操作是一個不斷重試的操作。樂觀鎖適合於頻繁查詢的操作。


未完待續…

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