public String stock() {
long threadId = Thread.currentThread().getId();
Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", threadId + "", 30, TimeUnit.SECONDS);
if (!lock) {
System.out.println("鎖未釋放");
return "";
}
//為了避免代碼未執行完鎖過期要進行鎖續期
new Thread() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(15000);
} catch (Exception e) {
e.fillInStackTrace();
}
String locked = redisTemplate.opsForValue().get("lock");
if (locked != null && !locked.equals("")) {
redisTemplate.expire("lock", 30, TimeUnit.SECONDS);
System.out.println("===================續期==============");
} else {
break;
}
}
}
}.start();
try {
int stock = Integer.parseInt(redisTemplate.opsForValue().get("stock"));
if (stock > 0) {
stock--;
redisTemplate.opsForValue().set("stock", stock + "");
System.out.println("下單成功減少庫存,剩余" + stock);
} else {
System.out.println("庫存不足");
}
} finally {
//洗掉當前執行緒的鎖
String lockValue = redisTemplate.opsForValue().get("lock");
if (Long.valueOf(lockValue) == threadId) {
redisTemplate.delete("lock");
}
}
return "end";
}
uj5u.com熱心網友回復:
續費執行緒未主動結束,如果拿到鎖的執行緒 A 釋放了鎖,續費執行緒 a1 在休眠期間執行緒 B 拿到鎖后,會產生新的續費執行緒 b1 ,a1 并不會結束。因為此時 a1 并不知道拿鎖的執行緒已經換了,你沒有判斷拿鎖的執行緒 id 是否為開辟這個續費執行緒的 id。然后同一時間可能有好多多多多多續費執行緒。uj5u.com熱心網友回復:
22行判斷條件改一下: if (locked != null && locked.equals(threadId+"")) 還有別的嗎uj5u.com熱心網友回復:
可以擴展的多了,1.鎖沒有阻塞,沒拿到鎖就不執行了,而不是等待,有些場景可能不適用。
2.如果加入阻塞后還要考慮鎖可不可以重入,如果鎖是阻塞的在拿到鎖后的邏輯里繼續拿鎖,那就會造成死鎖。(畢竟代碼是人寫的,沒準會犯這個錯誤)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/19304.html
標籤:Web 開發
