Я не смог воспроизвести случай, который вы упомянули , но я привел вам простой пример того, как я реализовал код.
@RestController
@RequestMapping("/event")
public class EventRestController extends BaseRestController {
private final EventService service;
@Autowired
public EventRestController(final EventService service) {
this.service = requireNonNull(service, "service can't be null");
}
@PutMapping(value = "/sync")
public Callable<ResponseEntity<Void>> syncOperation() {
return () -> service.syncOperation();
}
...
}
@Service
@Slf4j
public class EventServiceImpl implements EventService {
private final EventRepository repository;
private final ReentrantLock fairLock;
@Autowired
public EventServiceImpl(@Qualifier("eventRepository") final EventRepository repository) {
this.repository = requireNonNull(repository, "repository can't be null");
this.fairLock = new ReentrantLock(true);
}
@Override
public void syncOperation() {
log.debug("thread try to acquire lock");
boolean isLockAcquired = false;
try {
isLockAcquired = fairLock.tryLock(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
if (isLockAcquired) {
try {
log.debug("{} own the lock", Thread.currentThread().getName());
// heavy operation
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
} finally {
fairLock.unlock();
log.debug("thread unlock");
}
}
log.debug("thread - {} end of method", Thread.currentThread().getName());
}
...
}
Bash код, который вызывает конечную точку:
#!/bin/bash
MAX=$1
for (( c=1; c<=MAX; c++ ))
do
curl -X PUT http://localhost:2000/app/event/sync > /dev/null 2>&1 &
done
Вызов:
./sync.sh 5
Это запустит 5 процессов в фоновом режиме и 5 параллельных процессов вызовут конечную точку.
Журнал сообщений :
15:59:22.026 [task-1] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - thread try to aquire lock
15:59:22.026 [task-2] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - thread try to aquire lock
15:59:22.026 [task-3] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - thread try to aquire lock
15:59:22.026 [task-5] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - thread try to aquire lock
15:59:22.026 [task-4] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - thread try to aquire lock
15:59:22.026 [task-2] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - task-2 own the lock
15:59:24.027 [task-2] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - thread unlock
15:59:24.027 [task-3] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - task-3 own the lock
15:59:24.027 [task-2] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - thread - task-2 end of method
15:59:26.027 [task-3] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - thread unlock
15:59:26.028 [task-3] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - thread - task-3 end of method
15:59:26.028 [task-1] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - task-1 own the lock
15:59:28.029 [task-1] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - thread unlock
15:59:28.029 [task-5] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - task-5 own the lock
15:59:28.029 [task-1] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - thread - task-1 end of method
В примере мы видим, что поток task-2 успешно получает блокировку, а другие потоки пытаются получить блокировку, и они блокируются до task-2 снять блокировку, и thread-4 не получило блокировку в соответствующее время.
Я думаю, что эта часть интересна:
15:59:22.026 [task-2] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - task-2 own the lock
15:59:24.027 [task-2] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - thread unlock
15:59:24.027 [task-3] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - task-3 own the lock
15:59:24.027 [task-2] DEBUG hu.gaszabo.persistence.app.application.EventServiceImpl - thread - task-2 end of method
task-2 поток получил блокировку, через 2 секунды он снял блокировку, задача-3 поток немедленно получил блокировку до задача-2 сообщение об окончании потока завершено.
ответ от вас Вопрос может заключаться в том, что некоторые операции происходят одновременно (было бы лучше увидеть метки времени), но в журнале показано, что вы можете неправильно понять (например, то, что я показал, представляет эту ситуацию).