樂觀鎖( Optimistic Locking):顧名思義,對加鎖持有一種樂觀的態度,即先進行業務操做,不到最後一步不進行加鎖,"樂觀"的認爲加鎖必定會成功的,在最後一步更新數據的時候再進行加鎖。sql
悲觀鎖(Pessimistic Lock):正如其名字同樣,悲觀鎖對數據加鎖持有一種悲觀的態度。所以,在整個數據處理過程當中,將數據處於鎖定狀態。悲觀鎖的實現,每每依靠數據庫提供的鎖機制(也只有數據庫層提供的鎖機制才能真正保證數據訪問的排他性,不然,即便在本系統中實現了加鎖機制,也沒法保證外部系統不會修改數據)。數據庫
樂觀鎖:spa
version方式:通常是在數據表中加上一個數據版本號version字段,表示數據被修改的次數,當數據被修改時,version值會加一。當線程A要更新數據值時,在讀取數據的同時也會讀取version值,在提交更新時,若剛纔讀取到的version值爲當前數據庫中的version值相等時才更新,不然重試更新操做,直到更新成功。
sql實現代碼:線程
update table set x=x+1, version=version+1 where id=#{id} and version=#{version};
CAS操做方式:即compare and swap 或者 compare and set,
涉及到三個操做數,數據所在的內存值,預期值,新值。當須要更新時,判斷當前內存值與以前
取到的值是否相等,若相等,則用新值更新,若失敗則重試,通常狀況下是一個自旋操做,即不
斷的重試。code
悲觀鎖:blog
是由數據庫本身實現的,要用的時候,咱們直接調用數據庫的相關語句就能夠了(原理:共享資源每次只給一個線程使用,其它線程阻塞,用完後再把資源轉讓給其它線程),如行鎖、讀鎖和寫鎖等,都是在操做以前加鎖,在Java中,synchronized的思想也是悲觀鎖。內存
樂觀鎖:資源
比較適合讀取操做比較頻繁的場景,若是出現大量的寫入操做,數據發生衝突的可能性就會增大,爲了保證數據的一致性,應用層須要不斷的從新獲取數據,這樣會增長大量的查詢操做,下降了系統的吞吐量。io
悲觀鎖:table
比較適合寫入操做比較頻繁的場景,若是出現大量的讀取操做,每次讀取的時候都會進行加鎖,這樣會增長大量的鎖的開銷,下降了系統的吞吐量。
樂觀鎖的特色先進行業務操做,不到萬不得已不去拿鎖。即「樂觀」的認爲拿鎖多半是會成功的,所以在進行完業務操做須要實際更新數據的最後一步再去拿一下鎖就好。
悲觀鎖的特色是先獲取鎖,再進行業務操做,即「悲觀」的認爲獲取鎖是很是有可能失敗的,所以要先確保獲取鎖成功再進行業務操做。一般所說的「一鎖二查三更新」即指的是使用悲觀鎖。
簡而言之記得一句話:讀取頻繁使用樂觀鎖,寫入頻繁使用悲觀鎖。樂觀鎖不能解決髒讀的問題。