Я написал этот прослушиватель событий Spring, который обрабатывает запросы на обновление задач (хотя мой вопрос действительно не имеет ничего общего с Spring). Я хочу убедиться, что мы никогда не обрабатываем одновременно запросы на обновление одной и той же задачи. Для этого я поддерживаю Map
замков. Если карта содержит запись, ключ которой является идентификатором задачи, а значение — заблокированной блокировкой, это означает, что задача с этим идентификатором в настоящее время обновляется, и любая попытка обновить ее должна будет дождаться снятия блокировки. .
@Component
public class TaskUpdateEventListener {
private final ConcurrentMap<UUID, Lock> taskLocks = new ConcurrentHashMap<>();
@TransactionalEventListener
@Async
public void onTaskUpdate(TaskUpdateEvent taskUpdateEvent) {
var taskId = taskUpdateEvent.getTaskId();
var taskLock = taskLocks.computeIfAbsent(taskId, taskIdKey -> new ReentrantLock());
taskLock.lock();
try {
updateTask(taskId);
} finally {
// Notice that we never remove locks from the Map
taskLock.unlock();
}
}
private void updateTask(UUID taskId) {
// implementation omitted
}
}
В этой реализации мне не нравится то, что блокировки никогда не снимаются с taskLocks
. Я подозреваю, что должен быть способ гарантировать, что запросы на обновление одной и той же задачи обрабатываются последовательно без поддержки пула блокировок, например, используя условия блокировки.