From 2fbb6fbaf4e23ed5d58d815fc87fd03047140217 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Wed, 24 Jan 2018 17:26:33 -0500 Subject: [PATCH] Fix JdbcLockRegDiffClientTests race condition https://build.spring.io/browse/INT-MJATS41-1242 When different `DefaultLockRepository` instances use the same client id, there is a possibility that they will update the same row in the table. This way we have a chance that not only one obtains a lock and try to add a value to the collection. * Remove the test-case for the same client id as non-stable and even dangerous by the the distributed lock purpose * Use `tryLock(Long.MAX_VALUE)` to really ensure the wait behavior during the concurrent loop * Use `20` for thread pool to align with the tasks amount **Cherry-picked to 4.3.x** --- .../JdbcLockRegistryDifferentClientTests.java | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryDifferentClientTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryDifferentClientTests.java index c0200a2ff5..e3badd500d 100644 --- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryDifferentClientTests.java +++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryDifferentClientTests.java @@ -191,26 +191,19 @@ public class JdbcLockRegistryDifferentClientTests { @Test public void testOnlyOneLock() throws Exception { - testOnlyOneLock(null); - testOnlyOneLock("AABBCCDD"); - } - - private void testOnlyOneLock(String id) throws Exception { for (int i = 0; i < 100; i++) { final BlockingQueue locked = new LinkedBlockingQueue<>(); final CountDownLatch latch = new CountDownLatch(20); - ExecutorService pool = Executors.newFixedThreadPool(6); - ArrayList> tasks = new ArrayList>(); - final DefaultLockRepository client = (id == null) ? - new DefaultLockRepository(this.dataSource) : - new DefaultLockRepository(this.dataSource, id); - client.afterPropertiesSet(); - this.context.getAutowireCapableBeanFactory().autowireBean(client); + ExecutorService pool = Executors.newFixedThreadPool(20); + ArrayList> tasks = new ArrayList<>(); + for (int j = 0; j < 20; j++) { Callable task = () -> { + DefaultLockRepository client = new DefaultLockRepository(this.dataSource); + client.afterPropertiesSet(); Lock lock = new JdbcLockRegistry(client).obtain("foo"); try { - if (locked.isEmpty() && lock.tryLock()) { + if (locked.isEmpty() && lock.tryLock(Long.MAX_VALUE, TimeUnit.MILLISECONDS)) { if (locked.isEmpty()) { locked.add("done"); return true;