반응형
1️⃣ 동시 접근 제어란?
멀티스레드 환경에서 여러 스레드가 동시에 같은 자원에 접근할 수 있음.
문제는 동시에 읽기/쓰기가 일어나면 데이터 불일치나 경합이 발생한다는 것.
👉 이걸 막는 것이 바로 동시 접근 제어
2️⃣ 잠금을 이용한 접근 제어 (Lock-based Control)
🔒 Lock의 기본 개념
Lock은 "자원에 대한 접근권을 잠그는 기법".
한 스레드가 Lock을 획득하면, 다른 스레드는 그 Lock이 해제될 때까지 대기.
Java에서는 synchronized 키워드나 ReentrantLock이 대표적인 방법.
public class Counter {
private int count = 0;
private final ReentrantLock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
}
✅ 특징
- 단일 자원에 대한 상호 배제 보장
- 스레드 간 자원 경쟁 방지
- 블로킹 방식
⚠️ 주의
- 데드락, 교착 상태 위험
- Lock 획득 순서나 범위를 잘못 잡으면 성능 병목
💡 실무 팁
- 짧고 작은 범위에서만 Lock 사용
- 가능하다면 락 없는 알고리즘(Lock-free) 이나 원자적 연산 활용
3️⃣ 동시 접근 제어를 위한 구성요소
멀티스레드 환경에서 자원 접근을 제어하기 위해서는 다음 구성요소들이 함께 작동.
| 구성 요소 | 역할 | 예시 |
| 임계 영역 | 동시에 하나의 스레드만 접근해야 하는 코드구간 | count++ |
| 뮤텍스 | 한 번에 하나의 스레드만 접근하도록 제어 | ReentrantLock, synchronized |
| 세마포어 | 동시에 N개의 스레드까지 접근 허용 | Semaphore(3) |
| 모니터 | Lock + Condition을 함께 관리 | Java의 synchronized 블록 |
| 조건 변수 | 특정 조건이 충족될 때까지 대기 | wait(), notify() |
4️⃣ 세마포어 (Semaphore)
세마포어는 동시에 접근 가능한 스레드 수를 제한하는 도구.
네트워크 연결, 스레드 풀, 데이터베이스 커넥션 풀 등
동시 처리 수를 제한해야 하는 상황에서 자주 사용됨.
public class ConnectionPool {
private final Semaphore semaphore = new Semaphore(5); // 동시 5개 허용
public void connect() {
try {
semaphore.acquire();
// 실제 연결 처리
System.out.println("Connected: " + Thread.currentThread().getName());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
semaphore.release();
}
}
}
💡 실무 팁
- API rate limit, 외부 API 호출 제한 등에 유용
- Spring WebFlux + Semaphore로 비동기 백프레셔 구현 가능
5️⃣ 원자적 타입 (Atomic Types)
Java의 java.util.concurrent.atomic 패키지는
Lock을 사용하지 않고 CPU의 CAS 명령으로 원자적 연산을 보장함.
private final AtomicInteger counter = new AtomicInteger();
public void increment() {
counter.incrementAndGet();
}
✅ 장점
- 락 없이 원자성 보장
- 경합 없고 성능 좋음
- 단순한 카운터나 플래그 처리에 적합
⚠️ 단점
- 단일 변수 단위의 원자성만 보장
- 복합 연산에는 부적합
💡 실무 팁
- 메트릭 카운터, 큐 크기 모니터링, 단일 상태 플래그 등에 사용
- 복잡한 연산은 synchronized 또는 StampedLock으로 전환
6️⃣ 동시성 지원 컬렉션 (Concurrent Collections)
Java 표준 컬렉션(ArrayList, HashMap)은 스레드 안전하지 않음.
멀티스레드 환경에서는 Concurrent 패키지의 컬렉션을 써야함.
| 컬렉션 | 설명 | 특징 |
| ConcurrentHashMap | 멀티스레드용 Map | 세그먼트 락, 높은 성능 |
| ConcurrentLinkedQueue | 락 없는 큐 | CAS 기반, 대기 없음 |
| CopyOnWriteArrayList | 읽기 많은 환경용 리스트 | 변경 시 복사, 읽기 빠름 |
| BlockingQueue | 생산자-소비자 패턴용 | take()/put()로 스레드 대기 제 |
반응형
'DevOps' 카테고리의 다른 글
| 왜 우리는 환경마다 다른 배포 전략을 선택했을까? (0) | 2026.01.28 |
|---|---|
| 📨 Kafka vs RabbitMQ vs Redis Pub/Sub (0) | 2025.11.12 |
| 🌐 외부 연동 설계 — 타임아웃부터 서킷 브레이커까지 (0) | 2025.11.11 |
| ⚖️ CAP 정리 — 분산 시스템의 세 가지 불가능한 균형 (0) | 2025.10.29 |
| 🔍 DB 인덱스 - 빠른 검색의 비밀 (0) | 2025.10.28 |