This is an automated email from the ASF dual-hosted git repository.

ivandasch pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 2c930ab4eb8 IGNITE-20730 Fix IgniteLock cannot be acquired after 
release on JDK 17 (#11012)
2c930ab4eb8 is described below

commit 2c930ab4eb8336b9e2fa399521e8e5d4cc3f07c9
Author: Ivan Daschinskiy <[email protected]>
AuthorDate: Wed Oct 25 22:23:46 2023 +0300

    IGNITE-20730 Fix IgniteLock cannot be acquired after release on JDK 17 
(#11012)
---
 .../datastructures/GridCacheLockImpl.java          |  3 ++
 .../datastructures/IgniteLockAbstractSelfTest.java | 52 ++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheLockImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheLockImpl.java
index 3881820381b..22999476c38 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheLockImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheLockImpl.java
@@ -607,6 +607,9 @@ public final class GridCacheLockImpl extends 
AtomicDataStructureProxy<GridCacheL
                                 LinkedList<UUID> nodes = val.getNodes();
 
                                 if (!cancelled) {
+                                    if 
(sync.waitingThreads.contains(thread.getId()) && nodes.contains(thisNode))
+                                        return true;
+
                                     nodes.add(thisNode);
 
                                     val.setChanged(false);
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteLockAbstractSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteLockAbstractSelfTest.java
index 1d31bacedb3..2d9a069f9e6 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteLockAbstractSelfTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteLockAbstractSelfTest.java
@@ -28,11 +28,14 @@ import java.util.Random;
 import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteCheckedException;
@@ -113,6 +116,55 @@ public abstract class IgniteLockAbstractSelfTest extends 
IgniteAtomicsAbstractTe
         checkFailover(false, true);
     }
 
+    /**
+     * Tests that {@link IgniteLock} can be acquired after release, especially 
while running on JDK 17.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testFairLockIsAbleToBeAcquiredAfterRelease() throws Exception {
+        List<IgniteLock> locks = IntStream.range(0, NODES_CNT)
+            .mapToObj(i -> grid(i).reentrantLock("test", true, true, true))
+            .collect(Collectors.toList());
+
+        CountDownLatch lockEnterLatch = new CountDownLatch(NODES_CNT - 1);
+        locks.get(0).lock();
+        try {
+            acquireLockInSeparateThreads(locks.subList(1, NODES_CNT), 
lockEnterLatch);
+        }
+        finally {
+            locks.get(0).unlock();
+        }
+
+        assertTrue(lockEnterLatch.await(GridTestUtils.DFLT_TEST_TIMEOUT, 
TimeUnit.SECONDS));
+
+        // Try to acquire the first lock in separate thread.
+        lockEnterLatch = new CountDownLatch(1);
+        acquireLockInSeparateThreads(locks.subList(0, 1), lockEnterLatch);
+        assertTrue(lockEnterLatch.await(GridTestUtils.DFLT_TEST_TIMEOUT, 
TimeUnit.SECONDS));
+    }
+
+    /** */
+    private void acquireLockInSeparateThreads(List<IgniteLock> locks, 
CountDownLatch lockEnterLatch) throws Exception {
+        CountDownLatch startLatch = new CountDownLatch(locks.size());
+
+        for (IgniteLock lock: locks) {
+            GridTestUtils.runAsync(() -> {
+                startLatch.countDown();
+
+                lock.lock();
+                try {
+                    lockEnterLatch.countDown();
+                }
+                finally {
+                    lock.unlock();
+                }
+            });
+        }
+
+        assertTrue(startLatch.await(GridTestUtils.DFLT_TEST_TIMEOUT, 
TimeUnit.SECONDS));
+    }
+
     /**
      * Implementation of ignite data structures internally uses special system 
caches, need make sure
      * that transaction on these system caches do not intersect with 
transactions started by user.

Reply via email to