樂觀鎖:認為每次去拿資料的時候別人不會修改,所以不會上鎖,但是每次要拿資料的時候都會先判斷資料是否被別人修改
悲觀鎖:認為每次去拿資料的時候別人都會修改,所以每次都會上鎖。
使用場景:樂觀鎖使用於多讀少寫的應用型別,這樣可以提高吞吐量;相反的情況則使用悲觀鎖
樂觀鎖和悲觀鎖是併發控制中兩種常見的鎖機制,它們分別基於不同的假設來處理資料的併發訪問。
樂觀鎖
實現
- 版本號機制:在資料表中增加一個版本號欄位,每次更新資料時,版本號加1。更新前檢查版本號是否發生變化,如果發生變化則更新失敗。
UPDATE table SET value = ?, version = version + 1 WHERE id = ? AND version = ?
- 時間戳機制:在資料表中增加一個時間戳欄位,每次更新資料時,時間戳更新為當前時間。更新前檢查時間戳是否發生變化,如果發生變化則更新失敗。
UPDATE table SET value = ?, timestamp = CURRENT_TIMESTAMP WHERE id = ? AND timestamp = ?
場景
- 多讀少寫:適用於讀多寫少的場景,因為樂觀鎖在讀取資料時不加鎖,可以提高讀取的吞吐量。
- 低併發:適用於併發衝突較少的場景,因為樂觀鎖在更新資料時需要檢查資料是否被修改,如果衝突頻繁,可能會導致大量重試。
悲觀鎖
實現
- 資料庫鎖:使用資料庫的鎖機制,如
SELECT ... FOR UPDATE
。
SELECT * FROM table WHERE id = ? FOR UPDATE
- 程式語言級別的鎖:使用程式語言提供的鎖機制,如Java中的
synchronized
關鍵字或ReentrantLock
。
synchronized (lockObject) {
}
場景
- 多寫少讀:適用於寫多讀少的場景,因為悲觀鎖在讀取資料時就加鎖,可以確保資料的一致性。
- 高併發:適用於併發衝突較多的場景,因為悲觀鎖在讀取資料時就加鎖,可以避免頻繁的更新衝突。