Skip to content

Commit 40404f4

Browse files
committed
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** # Conflicts: # spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryDifferentClientTests.java
1 parent db52adc commit 40404f4

File tree

1 file changed

+21
-32
lines changed

1 file changed

+21
-32
lines changed

spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryDifferentClientTests.java

+21-32
Original file line numberDiff line numberDiff line change
@@ -199,46 +199,35 @@ public void run() {
199199

200200
@Test
201201
public void testOnlyOneLock() throws Exception {
202-
testOnlyOneLock(null);
203-
testOnlyOneLock("AABBCCDD");
204-
}
205-
206-
private void testOnlyOneLock(String id) throws Exception {
207202
for (int i = 0; i < 100; i++) {
208203
final BlockingQueue<String> locked = new LinkedBlockingQueue<>();
209204
final CountDownLatch latch = new CountDownLatch(20);
210-
ExecutorService pool = Executors.newFixedThreadPool(6);
211-
ArrayList<Callable<Boolean>> tasks = new ArrayList<Callable<Boolean>>();
212-
final DefaultLockRepository client = (id == null) ?
213-
new DefaultLockRepository(this.dataSource) :
214-
new DefaultLockRepository(this.dataSource, id);
215-
client.afterPropertiesSet();
216-
this.context.getAutowireCapableBeanFactory().autowireBean(client);
217-
for (int j = 0; j < 20; j++) {
218-
Callable<Boolean> task = new Callable<Boolean>() {
205+
ExecutorService pool = Executors.newFixedThreadPool(20);
206+
ArrayList<Callable<Boolean>> tasks = new ArrayList<>();
219207

220-
@Override
221-
public Boolean call() {
222-
Lock lock = new JdbcLockRegistry(client).obtain("foo");
223-
try {
224-
if (locked.isEmpty() && lock.tryLock()) {
225-
if (locked.isEmpty()) {
226-
locked.add("done");
227-
return true;
228-
}
208+
for (int j = 0; j < 20; j++) {
209+
Callable<Boolean> task = () -> {
210+
DefaultLockRepository client = new DefaultLockRepository(this.dataSource);
211+
client.afterPropertiesSet();
212+
Lock lock = new JdbcLockRegistry(client).obtain("foo");
213+
try {
214+
if (locked.isEmpty() && lock.tryLock(Long.MAX_VALUE, TimeUnit.MILLISECONDS)) {
215+
if (locked.isEmpty()) {
216+
locked.add("done");
217+
return true;
229218
}
230219
}
231-
finally {
232-
try {
233-
lock.unlock();
234-
}
235-
catch (Exception e) {
236-
// ignore
237-
}
238-
latch.countDown();
220+
}
221+
finally {
222+
try {
223+
lock.unlock();
239224
}
240-
return false;
225+
catch (Exception e) {
226+
// ignore
227+
}
228+
latch.countDown();
241229
}
230+
return false;
242231
};
243232
tasks.add(task);
244233
}

0 commit comments

Comments
 (0)