Spring LockRegistry:何时调用 LockRegistry.obtain()

mat*_*jes 0 java spring locking spring-integration

我不确定什么时候打电话RedisLockRegistry.obtain(String lockKey)(或者,更一般地说,LockRegistry.obtain(String lockKey))。我应该在应用程序开始时只获得一次锁,然后像往常一样锁定/解锁它,还是应该在每次调用 lock 之前(在我使用它之前)获得一个锁?

目前我正在使用后一个选项,但是,我不确定这是否真的有必要。

Art*_*lan 5

了解如何使用它的最佳方法是遵循框架中的现有模式。

我要说的最简单的示例是SimpleMessageStore

@Override
public void addMessagesToGroup(Object groupId, Message<?>... messages) {
    Lock lock = this.lockRegistry.obtain(groupId);
    try {
        lock.lockInterruptibly();
        boolean unlocked = false;
        ...
        }
        finally {
            if (!unlocked) {
                lock.unlock();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

作为一个使用场所。

另一个样本是AbstractCorrelatingMessageHandler

@Override
protected void handleMessageInternal(Message<?> message) throws Exception {
    Object correlationKey = this.correlationStrategy.getCorrelationKey(message);
...
    UUID groupIdUuid = UUIDConverter.getUUID(correlationKey);
    Lock lock = this.lockRegistry.obtain(groupIdUuid.toString());

    lock.lockInterruptibly();
    try {
    ...
    }
    finally {
        lock.unlock();
    }
}
Run Code Online (Sandbox Code Playgroud)

所以,是的,您总是obtain()在使用目标LockAPI之前调用。但总的来说,它不会受到伤害,不要重新获得它。让我们检查一下RedisLockRegistry代码:

public Lock obtain(Object lockKey) {
    Assert.isInstanceOf(String.class, lockKey);
    String path = (String) lockKey;
    return this.locks.computeIfAbsent(path, RedisLock::new);
}
Run Code Online (Sandbox Code Playgroud)

背后的想法LockRegistry,这obtain是为了让最终用户获得访问共享资源(Lock在我们的例子)独家。因此,如果您key的全局性如此之大,以至于在您的应用程序开始时就足以获得它的锁定,那么保留一个关联的Lock实例完全取决于您。