Java

[Effective Java] 11-2. 동기화

noahkim_ 2025. 1. 3. 02:53

조슈아 블로크 님의 "Effective Java" 책을 정리한 포스팅 입니다.

 

1. wait와 notify보다는 동시성 유틸리티를 애용하라

  • 사용하기기 아주 까다로움으로 고수준 동시성 유틸리티를 사용하자

 

실행자 프레임워크

  • 스레드 풀 관리와 작업 실행을 위한 구현 제공
  • 스레드 생성과 관리를 추상화하여 직접 스레드 작업을 제어하지 않아도 됨

 

동시성 컬렉션

  • 동시 접근을 처리하기 위해 내부적으로 락 매커니즘을 활용
  • 여러 메서드를 원자적으로 묶어 호출하는 일 불가

 

ConcurrentHashMap
BlockingQueue
  • 생산자-소비자 패턴에 적합
  • 큐가 비어 있을 떄 소비가자 대기하거나, 큐가 꽉 찼을 떄 생산자가 대기하는 방식으로 동작

 

동기화 장치

  • 멀티스레드 작업에서 스레드 간 협력을 지원하기 위한 유틸리티

 

CountDownLatch
  • 스레드가 특정 조건이 만족될 떄까지 기다리게 하는 도구
  • await(): 카운트가 0이 될 때까지 대기

 

2. 지연 초기화는 신중히 사용하라

지연 초기화

  • 필드의 초기화 시점을 그 값이 처음 필요할 때까지 늦추는 기법
  • 필드를 사용하는 인스턴스의 비율이 낮은 반면, 그 필드를 초기화하는 비용이 클 경우

 

장점 
  • 인스턴스 생성 시의 초기화 비용은 줄어듬

 

단점
  • 필드에 접근하는 비용은 커짐

 

멀티스레드 환경

synchronized 접근자
public class LazyInitExample {
    private Object field;

    public synchronized Object getField() {
        if (field == null) {
            field = new Object(); // 초기화
        }
        return field;
    }
}
  • 안전하고 직관적
  • 동기화 오버헤드 발생

 

지연 초기화 홀더 클래스
public class LazyInitExample {
    private static class Holder {
        private static final Object INSTANCE = new Object(); // 초기화
    }

    public static Object getInstance() {
        return Holder.INSTANCE;
    }
}
  • 성능 좋음
  • 스레드 안전
    • 클래스 로딩 시점의 스레드 안전성 활용

 

이중검사 관용구 사용
public class LazyInitExample {
    private volatile Object field;

    public Object getField() {
        if (field == null) { // 첫 번째 검사 (동기화 없음)
            synchronized (this) {
                if (field == null) { // 두 번째 검사 (동기화)
                    field = new Object(); // 초기화
                }
            }
        }
        return field;
    }
}
  • 초기화가 여러번 수행되지 않도록 두번 검사 수행

 

3. 프로그램의 동작을 스레드 스케줄러에 기대지 말라

의존하면 안되는 이유

동작의 비결정성
  • 스레드 스케줄러는 다양한 요인에 의존 (OS, JVM, CPU 등)

 

이식성 문제
  • 정확성이나 성능이 스레드 스케줄러에 따라 달라지는 프로그램일 경우, 다른 플랫폼에 이식하기 어려움

 

디버깅 어려움
성능 측정 어려움

 

의존하면 안되는 속성

Thread.yield
  • 현재 실행 중인 스레드가 자발적으로 CPU를 포기하고, 실행 준비 상태로 돌아가도록 요청하는 메서드
  • JVM과 OS 별로 동작되거나 안될 수 있음

 

스레드 우선순위
  • 스레드에 우선순위를 부여하는 힌트로 제공됨
  • JVM과 OS 별로 처리 방식이 다름

'Java' 카테고리의 다른 글

[Effective Java] 12-2. 직렬화  (1) 2025.01.03
[Effective Java] 12-1. 직렬화  (0) 2025.01.03
[Effective Java] 11-1. 동기화  (0) 2025.01.01
[Effective Java] 10-2. 예외  (0) 2025.01.01
[Effective Java] 10-1. 예외  (0) 2025.01.01