浅谈面试中的乐观锁与悲观锁
樂觀鎖與悲觀鎖
- 一、什么是樂觀鎖(Optimistic Locking)?
- 二、什么是悲觀鎖(Pessimistic Lock)?
- 悲觀鎖主要分為共享鎖和排他鎖
- 注意
- 三、并發控制
一、什么是樂觀鎖(Optimistic Locking)?
??樂觀鎖(Optimistic Lock)顧名思義,就是很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制。
??樂觀鎖是相對悲觀鎖而言的,樂觀鎖假設數據一般情況不會造成沖突,所以在數據進行提交更新的時候,才會正式對數據的沖突與否進行檢測,如果沖突,則返回給用戶異常信息,讓用戶決定如何去做。樂觀鎖適用于讀多寫少的場景,這樣可以提高程序的吞吐量。
??樂觀鎖采取了更加寬松的加鎖機制。也是為了避免數據庫幻讀、業務處理時間過長等原因引起數據處理錯誤的一種機制,但樂觀鎖不會刻意使用數據庫本身的鎖機制,而是依據數據本身來保證數據的正確性。樂觀鎖的實現:
??1.CAS 實現:Java 中java.util.concurrent.atomic包下面的原子變量使用了樂觀鎖的一種 CAS 實現方式。
??2.版本號控制:一般是在數據表中加上一個數據版本號 version 字段,表示數據被修改的次數。當數據被修改時,version 值會 +1。當線程 A 要更新數據時,在讀取數據的同時也會讀取 version 值,在提交更新時,若剛才讀取到的 version 值與當前數據庫中的 version 值相等時才更新,否則重試更新操作,直到更新成功。
??注意:樂觀并發控制導致事務之間的數據競爭(data race)的概率是非常小的,因此可以盡可能地進行下去,直到提交的時候才去鎖定,最后不會產生任何鎖與死鎖。
二、什么是悲觀鎖(Pessimistic Lock)?
??悲觀鎖(Pessimistic Lock)顧名思義,就是很悲觀,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會 block 直到它拿到鎖。傳統的關系型數據庫里邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。
??同時也可以這樣理解:當要對數據庫中的一條數據進行修改的時候,為了避免同時被其他人修改,最好的辦法就是直接對該數據進行加鎖以防止并發。這種借助數據庫鎖機制,在修改數據之前先鎖定,再修改的方式被稱之為悲觀并發控制【Pessimistic Concurrency Control,縮寫“PCC”,又名“悲觀鎖”】。
??悲觀鎖,具有強烈的獨占和排他特性。它指的是對數據被外界(包括本系統當前的其他事務,以及來自外部系統的事務處理)修改持保守態度。因此,在整個數據處理過程中,將數據處于鎖定狀態。悲觀鎖的實現,往往依靠數據庫提供的鎖機制(也只有數據庫層提供的鎖機制才能真正保證數據訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無法保證外部系統不會修改數據)。
??而為什么叫做悲觀鎖,是因為這是一種對數據的修改持有悲觀態度的并發控制方式。總是假設最壞的情況,每次讀取數據的時候都默認其他線程會更改數據,因此需要進行加鎖操作,當其他線程想要訪問數據時,都需要阻塞掛起。悲觀鎖的實現:
??1.傳統的關系型數據庫使用這種鎖機制,比如行鎖、表鎖、讀鎖、寫鎖等,都是在操作之前先上鎖。
??2.Java 里面的同步 synchronized 關鍵字的實現。
悲觀鎖主要分為共享鎖和排他鎖
- 共享鎖【shared locks】又稱為讀鎖,簡稱 S 鎖。顧名思義,共享鎖就是多個事務對于同一數據可以共享一把鎖,都能訪問到數據,但是只能讀不能修改。
- 排他鎖【exclusive locks】又稱為寫鎖,簡稱 X 鎖。顧名思義,排他鎖就是不能與其他鎖并存,如果一個事務獲取了一個數據行的排他鎖,其他事務就不能再獲取該行的其他鎖,包括共享鎖和排他鎖。獲取排他鎖的事務可以對數據行讀取和修改。
注意
??悲觀并發控制實際上是“先取鎖再訪問”的保守策略,為數據處理的安全提供了保證。但是在效率方面,處理加鎖的機制會讓數據庫產生額外的開銷,還有增加產生死鎖的機會。另外還會降低并行性,一個事務如果鎖定了某行數據,其他事務就必須等待該事務處理完才可以處理那行數據。
三、并發控制
??當程序中可能出現并發的情況時,就需要保證在并發情況下數據的準確性,以此確保當前用戶和其他用戶一起操作時,所得到的結果和他單獨操作時的結果是一樣的。這就叫做并發控制。并發控制的目的是保證一個用戶的工作不會對另一個用戶的工作產生不合理的影響。
??沒有做好并發控制,就可能導致臟讀、幻讀和不可重復讀等問題。
??常說的并發控制,一般都和數據庫管理系統(DBMS)有關。在 DBMS 中并發控制的任務,是確保多個事務同時增刪改查同一數據時,不破壞事務的隔離性、一致性和數據庫的統一性。
實現并發控制的主要手段又主要分為樂觀并發控制和悲觀并發控制兩種。
??而我們所知道的悲觀鎖還是樂觀鎖,都是人們定義出來的概念,可以認為它是一種構建的思想。其實不僅僅是關系型數據庫系統中有樂觀鎖和悲觀鎖的概念,像 hibernate、tair、memcache 等都有類似的概念。所以,不應該拿樂觀鎖、悲觀鎖和其他的數據庫鎖等進行對比。樂觀鎖比較適用于讀多寫少的情況(多讀場景),悲觀鎖比較適用于寫多讀少的情況(多寫場景)。
總結
以上是生活随笔為你收集整理的浅谈面试中的乐观锁与悲观锁的全部內容,希望文章能夠幫你解決所遇到的問題。