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