diff --git a/src/main/java/io/lettuce/core/protocol/SharedLock.java b/src/main/java/io/lettuce/core/protocol/SharedLock.java index a99f153d0e..f2e90186ee 100644 --- a/src/main/java/io/lettuce/core/protocol/SharedLock.java +++ b/src/main/java/io/lettuce/core/protocol/SharedLock.java @@ -146,9 +146,13 @@ private void lockWritersExclusive() { private void unlockWritersExclusive() { if (exclusiveLockOwner == Thread.currentThread()) { + // check exclusive look not reentrant first if (WRITERS.compareAndSet(this, -1, sharedCnt.get())) { exclusiveLockOwner = null; + return; } + // otherwise unlock until no more reentrant left + WRITERS.incrementAndGet(this); } } diff --git a/src/test/java/io/lettuce/core/protocol/SharedLockTest.java b/src/test/java/io/lettuce/core/protocol/SharedLockTest.java index 3dda418e66..a10e712ae4 100644 --- a/src/test/java/io/lettuce/core/protocol/SharedLockTest.java +++ b/src/test/java/io/lettuce/core/protocol/SharedLockTest.java @@ -27,7 +27,8 @@ public void safety_on_reentrant_lock_exclusive_on_writers() throws InterruptedEx sharedLock.decrementWriters(); } - cnt.await(1, TimeUnit.SECONDS); + boolean await = cnt.await(1, TimeUnit.SECONDS); + Assertions.assertTrue(await); // verify writers won't be negative after finally decrementWriters String result = sharedLock.doExclusive(() -> { @@ -37,6 +38,20 @@ public void safety_on_reentrant_lock_exclusive_on_writers() throws InterruptedEx }); Assertions.assertEquals("ok", result); + + // and other writers should be passed after exclusive lock released + CountDownLatch cntOtherThread = new CountDownLatch(1); + new Thread(() -> { + try { + sharedLock.incrementWriters(); + cntOtherThread.countDown(); + } finally { + sharedLock.decrementWriters(); + } + }).start(); + + await = cntOtherThread.await(1, TimeUnit.SECONDS); + Assertions.assertTrue(await); } }