스레드와 동시성
여러 작업을 동시에 처리할 때 발생하는 문제와 해결 방법을 직접 체험합니다.
왜 알아야 하나요?
월요일 아침, 급하게 호출이 왔습니다
"결제 금액이 이상해요. 10,000원 상품인데 어떤 고객은 0원으로 결제됐대요!"
로그를 확인해보니...
두 명이 동시에 같은 쿠폰을 사용했고, 둘 다 100% 할인이 적용됐습니다.
이것이 바로 Race Condition!
동시성을 이해하면 이런 버그를 예방할 수 있습니다.
한눈에 보기
여러 스레드가 동시에 같은 데이터를 수정하면 결과가 꼬입니다.
예: 재고 1개인데 2명이 동시 구매 → 재고 -1
두 스레드가 서로의 자원을 기다리며 영원히 멈춥니다.
예: A가 B를 기다리고, B가 A를 기다림
스레드를 미리 만들어두고 재사용해서 효율적으로 관리합니다.
예: 요청마다 스레드 생성 → 메모리 폭발
핵심 개념
프로그램 안에서 독립적으로 실행되는 작업 흐름입니다. 한 프로그램이 여러 일을 동시에 하려면 스레드가 여러 개 필요해요.
- 종업원 1명 = 한 번에 한 테이블만 서빙
- 종업원 4명 = 동시에 4 테이블 서빙 가능
- 하지만! 같은 주문서를 동시에 수정하면 문제 발생
여러 스레드가 순서대로 자원에 접근하도록 제어하는 것입니다. "한 번에 한 명씩만!" 규칙을 만드는 거예요.
synchronized: 가장 기본적인 락AtomicInteger: 숫자 연산을 원자적으로ReentrantLock: 더 세밀한 제어 가능
실무에서는
new Thread().start() 남발→ 스레드 수천 개 → 메모리 폭발
→ 데이터 손실, 버그 재현 어려움
→ 병렬 처리 효과 없음, 느려짐
ExecutorService 사용→ 스레드 재사용, 안정적 관리
AtomicInteger로 카운터 관리→ 락 없이도 안전한 증감
→ 항상 A → B 순서로 락 획득
직접 체험하기
각 탭을 선택해서 동시성 문제를 직접 발생시키고 해결해보세요.
온라인 쇼핑몰에 한정판 운동화가 딱 1개 남았어요. 그런데 두 명이 동시에 구매 버튼을 눌렀어요!
결과: 둘 다 구매 성공? 재고가 -1개가 되어버렸어요!
Race Condition: 여러 스레드가 동시에 같은 데이터를 수정하면 발생
해결책: synchronized, AtomicInteger, Lock 등으로 한 번에 한 명씩 처리
은행 ATM도 마찬가지! 잔액 조회 → 출금 사이에 다른 거래가 끼어들면 안 돼요.
더 알아보기
다음 단계
- • Connection Pool - DB 연결 관리
- • Caching - Redis 캐시 전략
- • Message Queue - 비동기 처리
참고 자료
- • Java Concurrency in Practice (책)
- • jconsole, VisualVM (모니터링 도구)
- • Thread Dump 분석 방법