測試可重入鎖
概念
可重入鎖就是在一段程式碼(多執行緒呼叫也包括)中能夠重複獲取同一把鎖。例如:A和B兩個方法同時需要獲取同把鎖,在A方法獲取鎖後,B方法同樣可以獲取該鎖執行業務邏輯。程式碼
@Test void ReentrantLockTest() { long threadId = Thread.currentThread().getId(); RLock lock = redissonClient.getLock("lock" + threadId); try { boolean isLockFirst = lock.tryLock(10000L, TimeUnit.SECONDS); System.out.println(isLockFirst ? "初次獲取鎖成功": "初次獲取鎖鎖失敗"); boolean isLockSecond = lock.tryLock(10000L, TimeUnit.SECONDS); System.out.println(isLockSecond ? "再次獲取鎖成功": "再次獲取鎖鎖失敗"); } catch (InterruptedException e) { log.error(String.valueOf(e)); } finally { System.out.println("釋放鎖"); lock.unlock(); } }
執行結果
分析
可以看出初次獲取鎖成功後,沒有等待鎖釋放,又一次成功獲取了鎖。這是因為Redisson利用hash結構記錄執行緒id和重入次數。
思考
但是如果A、B兩個方法同時對資料表中的同一個資料進行修改時,會不會破壞資料一致性呢?
測試不可重入鎖
概念
不可重入鎖就是在一段程式碼(多執行緒呼叫也包括)中不能夠重複獲取同一把鎖。例如:A和B兩個方法同時需要獲取同把鎖,在A方法獲取鎖後,B方法便不能獲取該鎖,只能被阻塞或執行失敗。
程式碼
@Test void notReentrantLockTest() { long threadId = Thread.currentThread().getId(); try { Boolean isLockFirst = stringRedisTemplate.opsForValue().setIfAbsent("lock" + threadId, "1", 1000, TimeUnit.SECONDS); System.out.println(Boolean.TRUE.equals(isLockFirst) ? "初次獲取鎖成功": "初次獲取鎖鎖失敗"); Boolean isLockSecond = stringRedisTemplate.opsForValue().setIfAbsent("lock" + threadId, "1", 1000, TimeUnit.SECONDS); System.out.println(Boolean.TRUE.equals(isLockSecond) ? "再次獲取鎖成功": "再次獲取鎖鎖失敗"); } catch (Exception e) { log.error(String.valueOf(e)); } finally { System.out.println("釋放鎖"); stringRedisTemplate.delete("lock" + threadId); } }
執行結果
分析
可以看出初次獲取鎖成功後,再次獲取鎖失敗了,只能等待鎖被釋放後才能再次加鎖。