對於樂觀鎖和悲觀鎖的區別及應用,要牢記一句話:讀取頻繁使用樂觀鎖,寫入頻繁使用悲觀鎖
本文轉自:https://blog.csdn.net/L_BestCoder/article/details/79298417
一、樂觀鎖(Optimistic Lock)
總是認爲不會產生併發問題,每次去取數據的時候總認爲不會有其他線程對數據進行修改,因此不會上鎖,但是在更新時會判斷其他線程在這之前有沒有對數據進行修改,一般會使用版本號機制或CAS操作實現。
樂觀鎖適用於多讀的應用類型,這樣可以提高吞吐量,像數據庫如果提供類似於write_condition機制的其實都是提供的樂觀鎖。
1、version方式:
一般是在數據表中加上一個數據版本號version字段,表示數據被修改的次數,當數據被修改時,version值會加一。當線程A要更新數據值時,在讀取數據的同時也會讀取version值,在提交更新時,若剛纔讀取到的version值爲當前數據庫中的version值相等時才更新,否則重試更新操作,直到更新成功。
核心SQL代碼:
update table set x=x+1, version=version+1 where id=#{id} and version=#{version};
2、CAS(定義見後)操作方式:
即compare and swap 或者 compare and set,涉及到三個操作數,數據所在的內存值,預期值,新值。當需要更新時,判斷當前內存值與之前取到的值是否相等,若相等,則用新值更新,若失敗則重試,一般情況下是一個自旋操作,即不斷的重試。
二、悲觀鎖(Pessimistic Lock):
顧名思義,就是很悲觀,總是假設最壞的情況,每次取數據時都認爲其他線程會修改,所以都會加鎖(讀鎖、寫鎖、行鎖等),當其他線程想要訪問數據時,都需要阻塞掛起。可以依靠數據庫實現,如行鎖、讀鎖和寫鎖等,都是在操作之前加鎖,在Java中,synchronized的思想也是悲觀鎖。
附:CAS(Compare and Swap)
CAS是由CPU硬件實現,所以執行相當快.CAS有三個操作參數:內存地址,期望值,要修改的新值,當期望值和內存當中的值進行比較不相等的時候,表示內存中的值已經被別線程改動過,這時候失敗返回,當相等的時候,將內存中的值改爲新的值,並返回成功。