01:00 ⇒ 이름 가명화 ETL 동작
SELECT NAME
FROM PATIENT
WHERE ID = 'evan';
결과
01:00 ⇒ 홍길동
01:01 ⇒ 홍**
데이터의 정합성 어긋나는 현상 발생!
원본 StockService
@Service
@RequiredArgsConstructor
public class StockService {
private final StockRepository stockRepository;
public void decrease(Long id, Long quantity) {
// get stock
Stock stock = stockRepository.findById(id).orElseThrow();
// 재고 감소
stock.decrease(quantity);
// 저장
stockRepository.saveAndFlush(stock);
}
}
Test
@DisplayName("동시 요청 테스트")
@Test
public void concurrency() throws InterruptedException {
int threadCount = 100;
ExecutorService executorService = Executors.newFixedThreadPool(32);
CountDownLatch latch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
executorService.submit(() -> {
try {
stockService.decrease(1L, 1L);
} finally {
latch.countDown();
}
});
}
latch.await();
Stock stock = stockRepository.findById(1L).orElseThrow();
// 100 - (1 * 100) = 0
assertEquals(0L, stock.getQuantity()); // **오류 발생!**
}
Race Condition
발생!
둘 이상의 스레드가 공유 데이터에 엑세스할 수 있고 동시에 변경하려고 할 때 발생하는 문제
하나의 스레드만 데이터에 엑세스할 수 있도록 해야한다!
개선된 StockService
@Service
@RequiredArgsConstructor
public class StockService {
private final StockRepository stockRepository;
public **synchronized** void decrease(Long id, Long quantity) {
// get stock
Stock stock = stockRepository.findById(id).orElseThrow();
// 재고 감소
stock.decrease(quantity);
// 저장
stockRepository.saveAndFlush(stock);
}
}