CompletableFuture和锁

时间:2017-05-30 13:30:39

标签: java multithreading locking guava completable-future

我有原始的同步代码

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();
}

锁定的目的是模仿更高级别的悲观数据库锁定。

在Java8中,引入了CompleteableFutures。 updateUserByUserId(userId);updateUserPropertiesByUserId(userId);现在可以返回CompletableFuture<Void>进行完全异步实施。

我的问题是,我如何使用相同的机制?或者这种锁定完全错误的方式? (我真的不想依赖数据库的锁定。如果可能的话,我想在app层而不是数据库层处理这个问题。

我试过了

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();
        });

但我一直在IllegalMonitorStateException lock.unlock();,这是预期的,因为你不应该在另一个线程中解锁。

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

您可以为回调的...Async variants提供执行程序,因此为锁定和解锁的一个回调提供相同的single threaded executor应该确保它们在同一个线程上执行。

Lock lock = getLock(userId); // get a lock from guava Striped locks
Executor lockExecutor = Executors.newSingleThreadExecutor();

return CompletableFuture
        .supplyAsync(() -> {
            lock.lock();
        }, lockExecutor)
        .thenCompose(VOID -> updateUserByUserId(userId))
        .thenCompose(entity -> updateUserPropertiesByUserId(userId))
        .whenCompleteAsync((entity, ex) -> {
            lock.unlock();
        }, lockExecutor);

注意:我没有运行它,希望它有效!