핵심 정리

synchronized

synchronized 키워드를 사용하면 그 필드는 한번에 하나의 스레드만 접근 가능하다. 즉 락이 걸린다.

@Service
public class StockService {
		@Transactional
    public synchronized void decrease(Long id, Long quantity) {
        Stock stock = stockRepository.findById(id).orElseThrow();
        stock.decrease(quantity);
    }
}

그럼에도 테스트는 실패하는데, 그 원인은 @Transactional 때문이다.

@Transactional

@Transactional는 스프링의 AOP로 구현된 기술이므로, 실제 동작할 때는 이 클래스를 래핑한 프록시 객체가 실행된다. 따라서 프록시 메서드 자체에는 synchronized가 붙어있지 않으므로 여전히 여러 스레드가 동시 접근한다.

스크린샷 2023-09-14 오후 5.52.49.png