一.正常加鎖
當兩個使用者同時註冊一個使用者名稱時,為保證使用者名稱不能重複,因此對其註冊的使用者名稱加鎖。
具體步驟:
獲得使用者註冊的使用者名稱,進行判斷,如果為空則對其進行加鎖,儲存到資料庫,釋放鎖資源。
二.執行緒出現阻塞
當A執行緒加鎖後出現阻塞時,導致資料還沒有存到資料庫,鎖的時間便會失效。
B執行緒便會執行,對資料進行加鎖,成功後儲存到資料庫,而這時A執行緒啟動,將資料儲存到資料庫,這時的資料便又會重複。
解決方法:
對鎖進行延期,加鎖成功後新建一個守護執行緒,監控鎖的過期時間,如果這個時間小於設定的時間,則會自動延期
問題:1.為何使用守護執行緒
不一定要用守護執行緒,只要能保證對鎖進行延期即可
2.為何要設定過期時間
為了避免出現特殊情況,導致鎖一直留在redis中,不能釋放,比如:斷電,刪除鎖失敗
三.網上對執行緒的說法
極端情況下以上的思路還是可能出現問題,比如:
- 有兩個執行緒A,B一前一後執行
- A執行緒正常執行,但是執行業務時間較長,並且守護執行緒阻塞或者延期失敗,導致鎖自動過期
- B執行緒又來加鎖,之後A執行緒繼續執行,最後釋放鎖,其實A執行緒加的鎖已經過期,釋放的是B執行緒的鎖
解決方法:
- 在執行setIfAbsent方法時,給key設定一個唯一值,如加uuid
- 在釋放鎖時,先判斷value對不對,再釋放