CountDownLatch 는 스레드 간 동기화를 위해 특정 조건이 완료될 때까지 대기하는 도구이다.
목적
- 여러 스레드가 작업을 끝낸 후 다음 단계를 진행하도록 보장
동작원리
- 초기 카운트를 설정하고, 각 작업 완료 시 countDown() 으로 카운트 감소
- await() 호출 스레드는 카운트가 0이 될 때까지 블록
주요 메서드
- CountDownLatch(int count): 초기 카운트 설정. 작업 수에 맞게 지정
- await(): 카운트가 0이 될 때까지 대기
- await(long timeout, TimeUnit unit): 타임아웃 설정 후 대기
- countDown(): 카운트 1 감소. 0이 되면 대기 해제
- getCount(): 현재 카운트 조회
장점
- 단순성 : 락보다 직관적이며, 작업 완료 시점에 동기화에 최적
- 유연성 : 작업 수를 카운트로 조정 가능
- 비동기 처리 : 대기 중 다른 스레드 작업 진행 가능
- 타임아웃 지원 : await(long, TimeUnit) 으로 제한 시간 설정 가능
단점
- 일회성 : 한번 사용 후 재사용이 불가능. 새 객체 생성 필요
- 원자성 없음 : total += value 같은 연산은 별도 동기화 필요
- 복잡한 조건에 부적합 : 다중 조건은 Condition 이나 다른 도구 권장
- 카운트 관리 : 초기값 잘못 설정 시 데드락 위험 (가장 아래 예제 참고)
주의점
- countDown() 누락 : 영원히 대기할 수 있음
- 공유 자원 보호 : total 처럼 공유 변수 시, synchronized 또는 Lock 추가 필요
- 타임아웃 처리: await() 타임아웃 후 로직 필요시 예외 처리
- 스레드 인터럽트 : InterruptedException 에 대한 대비 필요
public class LatchExample {
private int total = 0;
private final CountDownLatch latch = new CountDownLatch(2);
public void add(int value) {
total += value;
latch.countDown(); // 모든 스레드가 호출 안 하면 await() 영원히 대기
System.out.println(Thread.currentThread().getName() + " 작업 완료");
}
public int getTotal() {
return total;
}
public static void main(String[] args) throws InterruptedException {
LatchExample example = new LatchExample();
Thread t1 = new Thread(() -> {
example.add(10);
});
Thread t2 = new Thread(() -> {
example.add(20);
});
t1.start();
t2.start();
example.latch.await(); // 두 스레드 완료 대기
System.out.println("최종 합계: " + example.getTotal());
}
}
//출력값 (스레드 순서 다를 수 있음)
Thread-0 작업 완료
Thread-1 작업 완료
최종 합계: 30
CountDownLatch (=초기카운트) 개수와 countDown() 호출 수가 다르면 프로그램이 종료되지 않고 정지 상태발생(데드락)
메인 스레드가 대기 상태로 멈춘다.
예시) 초기카운트가 10개지만 스레드는 2개만 countDown() 호출할경우
private final CountDownLatch latch = new CountDownLatch(10);
Thread t1 = new Thread(() -> {
example.add(10);
});
Thread t2 = new Thread(() -> {
example.add(20);
});
여기서 마지막에 타임아웃을 설정해놓으면 종료는 가능하다.
example.latch.await(3, TimeUnit.SECONDS);
'Language > JAVA' 카테고리의 다른 글
[자바 멀티스레딩] 자바 동시성 고급: ConcurrentHashMap 사용법 (0) | 2025.04.01 |
---|---|
[자바 멀티스레딩] 자바 동시성 고급: ReentrantLock 사용법 (0) | 2025.03.30 |
[자바 멀티스레딩] 동시성 제어: volatile 사용법 (0) | 2025.03.28 |
[자바 멀티스레딩] 동기화: synchronized 과 AtomicInteger 사용법 (0) | 2025.03.28 |
[자바 멀티스레딩] 스레드 풀: ExecutorService 사용법 (0) | 2025.03.27 |
댓글