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