synchronized
키워드 활용method 선언부에 syncrhonized
키워드를 붙이면 해당 메소드에 하나의 thread만 접근할 수 있도록 제한한다.
public class StockService {
...
// @Transactional
public synchronized void decreaseStock(Long id, Long quantity) {
Stock stock = stockRepository.findById(id).orElseThrow();
stock.decrease(quantity);
stockRepository.saveAndFlush(stock);
}
}
@Transactional
사용에 주의하자해당 함수에 @Transactional
을 붙이게 되면 annotation의 동작 방식 때문에 의도한 대로 동작하지 않는다.
Spring에서는 @Transactional
이 붙은 메소드를 실행할 때 해당 클래스를 매핑한 클래스를 생성하여 실행한다.
이 때 트랜잭션 시작 ⭢ method 실행 ⭢ 트랜잭션 종료 순서로 진행 되는데, 트랜잭션이 종료될 때 상태가 데이터베이스에 업데이트된다.
method 실행은 완료되었지만 데이터베이스에 업데이트되지 않은 상황에서 다른 스레드가 해당 메서드에 접근할 때 동기화 문제가 다시 발생할 수 있다.
하나의 키워드를 통해 간단히 구현할 수 있다는 장점이 있지만, Java의 synchronized
는 하나의 프로세스 안에서만 보장된다.
따라서 여러 대의 서버에서 동시에 접근할 때는 보장하지 못하므로 실제 운용 서비스에서는 잘 사용하지 않는 방법이다.