成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

悲觀鎖與樂觀鎖的實現(詳情圖解)

開發 前端
這篇文章講解了悲觀鎖與樂觀鎖的區別,以及實現場景,不管是悲觀鎖還是樂觀鎖都是人們定義出來的概念,是一種思想。

[[390414]]

一、前言

1、在了解悲觀鎖和樂觀鎖之前,我們先了解一下什么是鎖,為什么要用到鎖?

2、技術來源于生活,鎖不僅在程序中存在,在現實中我們也隨處可見,例如我們上下班打卡的指紋鎖,保險柜上的密碼鎖,以及我們我們登錄的用戶名和密碼也是一種鎖,生活中用到鎖可以保護我們人身安全(指紋鎖)、財產安全(保險柜密碼鎖)、信息安全(用戶名密碼鎖),讓我們更放心的去使用和生活,因為有鎖,我們不用去擔心個人的財產和信息泄露。

3、而程序中的鎖,則是用來保證我們數據安全的機制和手段,例如當我們有多個線程去訪問修改共享變量的時候,我們可以給修改操作加鎖(syncronized)。當多個用戶修改表中同一數據時,我們可以給該行數據上鎖(行鎖)。因此,當程序中可能出現并發的情況時,我們就需要通過一定的手段來保證在并發情況下數據的準確性,通過這種手段保證了當前用戶和其他用戶一起操作時,所得到的結果和他單獨操作時的結果是一樣的

4、沒有做好并發控制,就可能導致臟讀、幻讀和不可重復讀等問題,如下圖所示:

由于并發操作,如果沒有加鎖進行并發控制,數據庫的最終的一條數據可能為3也有可能為5,導致數值不準確

二、悲觀鎖和樂觀鎖

首先我們需要清楚的一點就是無論是悲觀鎖還是樂觀鎖,都是人們定義出來的概念,可以認為是一種思想。

2.1、悲觀鎖

悲觀鎖(Pessimistic Lock): 就是很悲觀,每次去拿數據的時候都認為別人會修改。所以每次在拿數據的時候都會上鎖。這樣別人想拿數據就被擋住,直到悲觀鎖被釋放,悲觀鎖中的共享資源每次只給一個線程使用,其它線程阻塞,用完后再把資源轉讓給其它線程

但是在效率方面,處理加鎖的機制會產生額外的開銷,還有增加產生死鎖的機會。另外還會降低并行性,如果已經鎖定了一個線程A,其他線程就必須等待該線程A處理完才可以處理

數據庫中的行鎖,表鎖,讀鎖(共享鎖),寫鎖(排他鎖),以及syncronized實現的鎖均為悲觀鎖

悲觀并發控制實際上是“先取鎖再訪問”的保守策略,為數據處理的安全提供了保證

2.2、樂觀鎖

樂觀鎖(Optimistic Lock): 就是很樂觀,每次去拿數據的時候都認為別人不會修改。所以不會上鎖,但是如果想要更新數據,則會在更新前檢查在讀取至更新這段時間別人有沒有修改過這個數據。如果修改過,則重新讀取,再次嘗試更新,循環上述步驟直到更新成功(當然也允許更新失敗的線程放棄操作),樂觀鎖適用于多讀的應用類型,這樣可以提高吞吐量

相對于悲觀鎖,在對數據庫進行處理的時候,樂觀鎖并不會使用數據庫提供的鎖機制。一般的實現樂觀鎖的方式就是記錄數據版本(version)或者是時間戳來實現,不過使用版本記錄是最常用的。

樂觀控制相信事務之間的數據競爭(data race)的概率是比較小的,因此盡可能直接做下去,直到提交的時候才去鎖定,所以不會產生任何鎖和死鎖。

三、鎖的實現

悲觀鎖阻塞事務、樂觀鎖回滾重試:它們各有優缺點,不要認為一種一定好于另一種。像樂觀鎖適用于寫比較少的情況下,即沖突真的很少發生的時候,這樣可以省去鎖的開銷,加大了系統的整個吞吐量。但如果經常產生沖突,上層應用會不斷的進行重試,這樣反倒是降低了性能,所以這種情況下用悲觀鎖就比較合適。

3.1 悲觀鎖的實現方式

場景:

  • 有用戶A和用戶B,在同一家店鋪去購買同一個商品,但是商品的可購買數量只有一個

下面是這個店鋪的商品表t_goods結構和表中的數據:

在不加鎖的情況下,如果用戶A和用戶B同時下單,就會報錯。

悲觀鎖的實現,往往依靠數據庫提供的鎖機制,在數據庫中,我們如何用悲觀鎖去解決這個事情呢?

  1. 加入當用戶A對下單購買商品(臭豆腐)的時候,先去嘗試對該數據(臭豆腐)加上悲觀鎖
  2. 加鎖失敗:說明商品(臭豆腐)正在被其他事務進行修改,當前查詢需要等待或者拋出異常,具體返回的方式需要由開發者根據具體情況去定義
  3. 加鎖成功:對商品(臭豆腐)進行修改,也就是只有用戶A能買,用戶B想買(臭豆腐)就必須一直等待。當用戶A買好后,用戶B再想去買(臭豆腐)的時候會發現數量已經為0,那么B看到后就會放棄購買
  4. 在此期間如果有其他對該數據(臭豆腐)做修改或加鎖的操作,都會等待我們解鎖后或者直接拋出異常

那么如何加上悲觀鎖呢?我們可以通過以下語句給id=2的這行數據加上悲觀鎖,首先關閉MySQL數據庫的自動提交屬性。因為MySQL默認使用autocommit模式,也就是說,當我們執行一個更新操作后,MySQL會立刻將結果進行提交, (sql語句:setautocommit=0)

悲觀鎖加鎖sql語句:

  1. select num from t_goods where id = 2 for update 

我們通過開啟mysql的兩個會話,也就是兩個命令行來演示:

事務A:我們可以看到數據是立刻馬上就可以查詢出來,num=1

事務B:我們是可以看到,事務B會一直等待事務A釋放鎖。如果事務A長期不釋放鎖,那么最終事務B將會報錯,報錯如下圖所示,表示語句已被鎖住。

現在我們讓事務A執行命令去修改數據,讓臭豆腐的數量減一,然后查看修改后的數據,最后commit,結束事務

我們可以看到當我們事務A執行完成之后,臭豆腐的庫存只有0個了,這個時候我們用戶B再來購買這個臭豆腐的時候就會發現,最后一個臭豆腐已經被用戶A購買完了,那么用戶B只能放棄購買臭豆腐了。

通過悲觀鎖我們可以解決因為商品庫存不足,導致的商品超出庫存的售賣。

3.1 樂觀鎖的實現方式

對于上面的應用場景,我們應該怎么用樂觀鎖去解決呢?在上面的樂觀鎖中,我們有提到使用版本號(version)來解決,所以我們需要在t_goods加上版本號,調整后的sql表結構如下:

具體操作步驟如下:

1、首先用戶A和用戶B同時將臭豆腐(id=2)的數據查出來

2、然后用戶A先買,用戶A將(id=1和version=0)作為條件進行數據更新,將數量-1,并且將版本號+1。此時版本號變為1。用戶A此時就完成了商品的購買

3、 用戶B開始買,用戶B也將(id=1和version=0)作為條件進行數據更新

4、更新完后,發現更新的數據行數為0,此時就說明已經有人改動過數據,此時就應該提示用戶B重新查看最新數據購買

1、首先我們開啟兩個會話窗口,輸入查詢語句:selectnumfromt_goodswhere id=2

事務A:

事務B:

這個時候事務A和事務B同時獲取相同的數據

2、此時事務A進行更新數據的操作,然后在查詢更新后的數據

這個時候我們可以看到事務A更新成功,并且庫存-1 版本號+1成功

2、此時事務B進行更新數據的操作,然后在查詢更新后的數據

可以看到最終修改的時候失敗,數據沒有改變。此時就需要我們告知用戶B重新處理

3.1.1 CAS

說到樂觀鎖,就必須提到一個概念:CAS 什么是CAS呢?Compare-and-Swap,即比較并替換,也有叫做Compare-and-Set的,比較并設置。1、比較:讀取到了一個值A,在將其更新為B之前,檢查原值是否仍為A(未被其他線程改動)。2、設置:如果是,將A更新為B,結束。[1]如果不是,則什么都不做。上面的兩步操作是原子性的,可以簡單地理解為瞬間完成,在CPU看來就是一步操作。有了CAS,就可以實現一個樂觀鎖,允許多個線程同時讀取(因為根本沒有加鎖操作),但是只有一個線程可以成功更新數據,并導致其他要更新數據的線程回滾重試。CAS利用CPU指令,從硬件層面保證了操作的原子性,以達到類似于鎖的效果。

Java中真正的CAS操作調用的native方法因為整個過程中并沒有“加鎖”和“解鎖”操作,因此樂觀鎖策略也被稱為無鎖編程。換句話說,樂觀鎖其實不是“鎖”,它僅僅是一個循環重試CAS的算法而已!

四、如何選擇

悲觀鎖阻塞事務,樂觀鎖回滾重試,它們各有優缺點,不要認為一種一定好于另一種。像樂觀鎖適用于寫比較少的情況下,即沖突真的很少發生的時候,這樣可以省去鎖的開銷,加大了系統的整個吞吐量。

但如果經常產生沖突,上層應用會不斷的進行重試,這樣反倒是降低了性能,所以這種情況下用悲觀鎖就比較合適。

注意點:

1、樂觀鎖并未真正加鎖,所以效率高。一旦鎖的粒度掌握不好,更新失敗的概率就會比較高,容易發生業務失敗。

2、悲觀鎖依賴數據庫鎖,效率低。更新失敗的概率比較低。

五、總結

這篇文章講解了悲觀鎖與樂觀鎖的區別,以及實現場景,不管是悲觀鎖還是樂觀鎖都是人們定義出來的概念,是一種思想,

 

責任編輯:姜華 來源: 牧小農
相關推薦

2024-05-17 09:33:22

樂觀鎖CASversion

2023-02-23 10:32:52

樂觀鎖

2024-01-29 01:08:01

悲觀鎖遞歸鎖讀寫鎖

2024-07-25 09:01:22

2024-09-03 15:14:42

2025-04-23 08:45:00

悲觀鎖樂觀鎖并發控制機制

2023-07-05 08:18:54

Atomic類樂觀鎖悲觀鎖

2011-08-18 13:44:42

Oracle悲觀鎖樂觀鎖

2019-04-19 09:48:53

樂觀鎖悲觀鎖數據庫

2019-05-05 10:15:42

悲觀鎖樂觀鎖數據安全

2019-11-28 16:00:06

重入鎖讀寫鎖樂觀鎖

2009-09-25 16:43:44

Hibernate悲觀Hibernate樂觀

2019-01-04 11:18:35

獨享鎖共享鎖非公平鎖

2020-07-06 08:03:32

Java悲觀鎖樂觀鎖

2024-01-05 16:43:30

數據庫線程

2018-07-31 10:10:06

MySQLInnoDB死鎖

2023-08-17 14:10:11

Java開發前端

2020-09-16 07:56:28

多線程讀寫鎖悲觀鎖

2010-08-18 09:00:38

數據庫

2020-10-22 08:21:37

樂觀鎖、悲觀鎖和MVC
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品一区二区三区四区五区 | 亚洲欧美在线观看视频 | 亚洲黄色一级毛片 | 一区二区视频在线 | 粉嫩av在线 | 久久最新 | 成人欧美一区二区三区黑人孕妇 | 国产精品日日摸夜夜添夜夜av | 成人免费网站www网站高清 | 五月婷婷婷 | 日韩精品在线免费观看视频 | 久久综合久久久 | 国产精品久久久久久一区二区三区 | 欧美一区二区三区在线播放 | 中文字幕 在线观看 | 国产欧美一区二区三区日本久久久 | 日韩在线免费 | 亚洲精品国产综合区久久久久久久 | 日韩一区二区三区在线 | 国产精品1 | 久久伊人精品 | 日韩在线精品 | 久久久久久久国产 | 日韩高清一区二区 | 国产成人福利在线观看 | 国产亚洲www | 一区二区三区欧美在线 | 亚洲国产中文在线 | 免费在线一区二区三区 | 国产精品久久久久久久久久久久 | 国产一区二区三区四区hd | 999久久久 | 美女视频三区 | 亚洲成网站 | 91精品国产色综合久久 | 国产精品视频免费看 | 成人精品视频在线观看 | 欧美a∨ | 一区二区视频 | 亚洲国产精品人人爽夜夜爽 | 色本道|