Skip to content

Commit

Permalink
Fix JdbcLockRegDiffClientTests race condition
Browse files Browse the repository at this point in the history
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
  • Loading branch information
artembilan committed Jan 24, 2018
1 parent db52adc commit 40404f4
Showing 1 changed file with 21 additions and 32 deletions.
Expand Up @@ -199,46 +199,35 @@ public void run() {

@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<String> locked = new LinkedBlockingQueue<>();
final CountDownLatch latch = new CountDownLatch(20);
ExecutorService pool = Executors.newFixedThreadPool(6);
ArrayList<Callable<Boolean>> tasks = new ArrayList<Callable<Boolean>>();
final DefaultLockRepository client = (id == null) ?
new DefaultLockRepository(this.dataSource) :
new DefaultLockRepository(this.dataSource, id);
client.afterPropertiesSet();
this.context.getAutowireCapableBeanFactory().autowireBean(client);
for (int j = 0; j < 20; j++) {
Callable<Boolean> task = new Callable<Boolean>() {
ExecutorService pool = Executors.newFixedThreadPool(20);
ArrayList<Callable<Boolean>> tasks = new ArrayList<>();

@Override
public Boolean call() {
Lock lock = new JdbcLockRegistry(client).obtain("foo");
try {
if (locked.isEmpty() && lock.tryLock()) {
if (locked.isEmpty()) {
locked.add("done");
return true;
}
for (int j = 0; j < 20; j++) {
Callable<Boolean> task = () -> {
DefaultLockRepository client = new DefaultLockRepository(this.dataSource);
client.afterPropertiesSet();
Lock lock = new JdbcLockRegistry(client).obtain("foo");
try {
if (locked.isEmpty() && lock.tryLock(Long.MAX_VALUE, TimeUnit.MILLISECONDS)) {
if (locked.isEmpty()) {
locked.add("done");
return true;
}
}
finally {
try {
lock.unlock();
}
catch (Exception e) {
// ignore
}
latch.countDown();
}
finally {
try {
lock.unlock();
}
return false;
catch (Exception e) {
// ignore
}
latch.countDown();
}
return false;
};
tasks.add(task);
}
Expand Down

0 comments on commit 40404f4

Please sign in to comment.