什么是樂觀鎖和悲觀鎖?這其實是人們定義出的一種思想,可以對應為在生活中樂觀的人和悲觀的人,樂觀鎖總是相信最好的情況,去相信別人不會修改自己的資料,在每次取資料的時候都不會上鎖,因此比較適用于讀多寫少的情況,而悲觀鎖恰恰相反,總是擔心別人會去修改自己的資料,所以在每一次取資料時都會上鎖,比較適用于寫多讀少的情況,
- 悲觀鎖
首先我們來了解一下悲觀鎖,悲觀鎖認為被它保護的資料不安全的,隨時都有可能變動,一個行程或執行緒拿到悲觀鎖后,其他的行程或執行緒都不能對該資料進行修改,只能等待鎖被釋放,下一個拿到鎖的行程才能進行修改,悲觀鎖是“先取鎖再訪問”的保守策略,為資料處理的安全提供了保證,但是在效率方面,處理加鎖的機制會產生額外的開銷,還有增加產生死鎖的機會,另外還會降低并行性,一個行程或執行緒如果鎖定了某個資料,其他行程或執行緒就必須等待其處理完才可以處理那個資料,
悲觀鎖的實作:
1.傳統的關系型資料庫使用這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖,
2.Java 里面的 synchronized和ReentrantLock獨占鎖也屬于悲觀鎖, - 樂觀鎖
樂觀鎖的樂觀是相對于悲觀鎖而言的,樂觀鎖的樂觀體現在,它認為資料的變動不會太頻繁,因此它允許多個行程或執行緒同時對資料進行訪問和修改,但是樂觀鎖也不是毫無安全性可言,樂觀鎖會在資料進行提交更新的時候去判斷別人有沒有去修改這個資料,如果發現出現了沖突,則回傳給用戶錯誤的資訊,讓用戶重新去操作,樂觀鎖機制采取了更寬松的加鎖機制,適用于讀操作多的情況,可以提高程式的吞吐量,不會產生死鎖的情況,
樂觀鎖的實作:
CAS 實作:Java 中java.util.concurrent.atomic包下面的原子變數使用了樂觀鎖的一種 CAS 實作方式,
版本號控制:通常是在資料表中加上一個資料版本號 version 欄位,表示資料被修改的次數,當資料被修改時,version 值會+1,當執行緒A要更新資料值時,在讀取資料的同時也會讀取 version 值,在提交更新時,若剛才讀取到的 version 值與當前資料庫中的 version 值相等時才更新,否則重試更新操作,直到更新成功,
樂觀鎖與悲觀鎖的對比與選擇:
1.回應效率:如果需要高回應速度,推薦使用樂觀鎖,成功就執行,不成功就失敗,不需要等待其他行程去釋放鎖,
2.沖突頻率:如果沖突頻率高,推薦使用悲觀鎖,保證成功率,沖突頻率高的話,選擇樂觀鎖會需要多次重試才能成功,代價較大,
3.重試代價:如果重試代價大,推薦使用悲觀鎖,悲觀鎖依賴資料庫鎖,雖然效率較低,但失敗的概率也比較低,
4.還有一點區別是,使用樂觀鎖如果有人在你之前更新了資料,那么你的更新是被拒絕的,回傳至用戶重新操作,而悲觀鎖則會等待前一個行程把資料更新完成,再去進行操作,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/271257.html
標籤:其他
