티스토리 뷰
레이스 컨디션(Race Condition)
: 동시성 프로그래밍의 복잡성을 보여주는 단적인 사례.
- 두 개 이상의 프로세스나 스레드가 동일한 자원(데이터, 메모리 등)에 동시 접근할 때,
실행 순서에 따라 의도치 않은 결과가 발생하는 상황을 의미한다
- 즉, 처리 순서가 예측 불가능하여, 논리적인 버그나 예상치 못한 동작이 발생할 수 있는 문제라고 할 수 있다. 이는 병렬 처리(멀티스레딩, 비동기 프로그래밍)나 동시성 프로그래밍 환경에서 자주 나타난다.
레이스 컨디션 특징
1. 비결정성(Non-deterministic Behavior)
- 실행할 때마다 결과가 달라질 수 있다.
2. 공유 자원 문제
- 여러 프로세스/스레드가 공유 자원(변수/메모리 등)에 동시에 접속하여 충돌이 발생.
3. 타이밍 의존성
- 작업이 수행되는 정확한 타이밍에 따라 결과가 달라질 수 있다.
레이스 컨디션 예시
1. 멀티스레딩 예시
- 다중 스레드 환경에서 동일한 변수를 수정하는 상황
import threading
counter = 0
def increment():
global counter
for _ in range(1000):
counter += 1
threads = []
for i in range(5): # 5개의 스레드 생성
t = threading.Thread(target=increment)
threads.append(t)
t.start()
for t in threads:
t.join()
print(counter) # 결과가 5000이 아닐 수 있음 (레이스 컨디션 발생)
=> 문제 : 여러 스레드가 counter 값을 동시에 읽고 수정하므로, 값이 정확하게 업데이트되지 않는다.
2. 로그인 시스템에서의 예시
- 사용자가 동시에 두 번 로그인 요청을 보냈을 때
- 서버가 같은 게정에 대해 두 개의 세션을 생성한다.
- 나중에 생성된 세션이 이전 세션을 덮어쓰거나 둘 다 유효하지 않게 만든다.
레이스 컨디션의 주요 원인
1. 동시 접근(Concurrent Access)
- 여러 프로세스/스레드가 동일한 자원에 접근.
2. 공유 자원
- 공유 자원(변수, 데이터베이스, 파일 등)을 동기화하지 않고 접근
3. 타이밍 이슈
- 작업 실행 순서를 보장하지 않음.
4. 비동기/멀티스레드 환경
- 비동기 작업 또는 멀티스레드 프로그래밍에서 타이밍 문제 때문에 발생한다.
해결 방법
1. 락(Lock) 사용
- 스레드가 자원을 사용할 때 다른 스레드가 접근하지 못하도록 잠금을 설정
[예시]
import threading
lock = threading.Lock()
counter = 0
def increment():
global counter
for _ in range(1000):
with lock: # 락을 사용하여 동기화
counter += 1
threads = []
for i in range(5):
t = threading.Thread(target=increment)
threads.append(t)
t.start()
for t in threads:
t.join()
print(counter) # 항상 5000
2. 동기화(Synchronization)
- 공유 자원에 접근하는 코드(크리티컬 섹션)을 동기화.
- 상호 배제(Mutual Exclusion) 사용
3. 원자성(Atomicity) 보장
- 공유 변수에 대한 작업을 원자적으로 수행
- 예시 : 데이터베이스 트랜잭션, Interlocked 함수 등.
4. 타이밍 제어
- 코드의 실행 순서를 명시적으로 제어하여 충돌 방지.
5. 비동기 프로그래밍 관리
- Promise와 async/await 으로 실행 순서를 명확하게 정의.
사례
전자상거래 시스템
- 두 사용자가 동시에 동일한 상품을 구매할 경우, 재고가 초과되는 문제
금융 어플리케이션
- 계좌에서 동시에 출금 요청이 들어와 잔액이 음수가 되는 문제
파일 접근
- 여러 프로그램이 동시에 파일을 읽고 쓰는 경우, 파일 데이터가 손상.
'[기획자의 개발일기]' 카테고리의 다른 글
깃 브랜치 생성/이동/삭제 (0) | 2025.01.29 |
---|---|
nvm 설치 및 개발환경 세팅 (0) | 2025.01.05 |
소셜로그인과 토큰 (0) | 2025.01.01 |
SQL 스크립트에서 왜 '?'를 사용할까? (0) | 2024.12.30 |