@@ -711,11 +711,57 @@ public int hashCode() {
711711 // Force all CollidingKey instances to have the same hash code
712712 return 42 ;
713713 }
714+ }@ SuppressWarnings ("deprecation" )
715+ @ Test
716+ void getOrComputeIfAbsentDoesNotDeadlockWithCollidingKeys () throws Exception {
717+ var store = new NamespacedHierarchicalStore <String >(null );
718+ var latch1 = new CountDownLatch (1 );
719+ var latch2 = new CountDownLatch (1 );
720+
721+ var thread1 = new Thread (() -> {
722+ store .getOrComputeIfAbsent ("ns" , new CollidingKey (1 ), key -> {
723+ latch1 .countDown ();
724+ try {
725+ // Wait for second thread to start its computation
726+ latch2 .await ();
727+ }
728+ catch (InterruptedException e ) {
729+ Thread .currentThread ().interrupt ();
730+ throw new RuntimeException (e );
731+ }
732+ return "value1" ;
733+ });
734+ });
735+
736+ var thread2 = new Thread (() -> {
737+ try {
738+ // Wait for first thread to start its computation
739+ latch1 .await ();
740+ store .getOrComputeIfAbsent ("ns" , new CollidingKey (2 ), key -> {
741+ latch2 .countDown ();
742+ return "value2" ;
743+ });
744+ }
745+ catch (InterruptedException e ) {
746+ Thread .currentThread ().interrupt ();
747+ throw new RuntimeException (e );
748+ }
749+ });
750+
751+ thread1 .start ();
752+ thread2 .start ();
753+
754+ // Wait with timeout to detect deadlocks
755+ thread1 .join (5000 );
756+ thread2 .join (5000 );
757+
758+ assertFalse (thread1 .isAlive (), "Thread1 should have completed (no deadlock)" );
759+ assertFalse (thread2 .isAlive (), "Thread2 should have completed (no deadlock)" );
714760 }
715761
716762 @ SuppressWarnings ("deprecation" )
717763 @ Test
718- void getOrComputeIfAbsentDoesNotDeadlockWithCollidingKeys () throws Exception {
764+ void getOrComputeIfAbsentDoesNotDeadlockWithCollidingKeys2 () throws Exception {
719765 try (var localStore = new NamespacedHierarchicalStore <String >(null )) {
720766 var firstComputationStarted = new CountDownLatch (1 );
721767 var secondComputationAllowedToFinish = new CountDownLatch (1 );
@@ -1149,54 +1195,6 @@ void computeIfAbsentWithExceptionInMemoizingSupplierPropagation() {
11491195
11501196 }
11511197
1152- @ SuppressWarnings ("deprecation" )
1153- @ Test
1154- void getOrComputeIfAbsentDoesNotDeadlockWithCollidingKeys () throws Exception {
1155- var store = new NamespacedHierarchicalStore <String >(null );
1156- var latch1 = new CountDownLatch (1 );
1157- var latch2 = new CountDownLatch (1 );
1158-
1159- var thread1 = new Thread (() -> {
1160- store .getOrComputeIfAbsent ("ns" , new CollidingKey (1 ), key -> {
1161- latch1 .countDown ();
1162- try {
1163- // Wait for second thread to start its computation
1164- latch2 .await ();
1165- }
1166- catch (InterruptedException e ) {
1167- Thread .currentThread ().interrupt ();
1168- throw new RuntimeException (e );
1169- }
1170- return "value1" ;
1171- });
1172- });
1173-
1174- var thread2 = new Thread (() -> {
1175- try {
1176- // Wait for first thread to start its computation
1177- latch1 .await ();
1178- store .getOrComputeIfAbsent ("ns" , new CollidingKey (2 ), key -> {
1179- latch2 .countDown ();
1180- return "value2" ;
1181- });
1182- }
1183- catch (InterruptedException e ) {
1184- Thread .currentThread ().interrupt ();
1185- throw new RuntimeException (e );
1186- }
1187- });
1188-
1189- thread1 .start ();
1190- thread2 .start ();
1191-
1192- // Wait with timeout to detect deadlocks
1193- thread1 .join (5000 );
1194- thread2 .join (5000 );
1195-
1196- assertFalse (thread1 .isAlive (), "Thread1 should have completed (no deadlock)" );
1197- assertFalse (thread2 .isAlive (), "Thread2 should have completed (no deadlock)" );
1198- }
1199-
12001198 @ Test
12011199 void computeIfAbsentOverridesParentNullValue () {
12021200 var parent = new NamespacedHierarchicalStore <String >(null );
0 commit comments