I have the original synchronous code,
Lock lock = getLock(userId); // get a lock from guava Striped locks
lock.lock();
try {
// do some database writing action
updateUserByUserId(userId);
return updateUserPropertiesByUserId(userId);
}
finally {
lock.unlock();
}
The purpose of the lock is to mimic pessimistic database locking at a higher level.
In Java8, CompleteableFutures are introduced. And updateUserByUserId(userId); and updateUserPropertiesByUserId(userId); can now return CompletableFuture<Void> for a fully async implementation.
My question is, how can I employ the same mechanism? or is this way of locking completely wrong? (I don't really want to rely on the database's locking. If possible, I want to handle this in the app layer instead of the database layer)
I have tried
Lock lock = getLock(userId); // get a lock from guava Striped locks
return CompletableFuture
.supplyAsync(() -> {
lock.lock();
})
.thenCompose(VOID -> updateUserByUserId(userId))
.thenCompose(entity -> updateUserPropertiesByUserId(userId))
.whenComplete((entity, ex) -> {
lock.unlock();
});
But I've been getting IllegalMonitorStateException on lock.unlock();, which is expected, because you're not supposed to unlock a lock in a different thread.
Any suggestions?