-
Notifications
You must be signed in to change notification settings - Fork 0
ㄴ 11장 동시성
동기화할 때는 쓰기와 읽기 모두가 동기화되어야 한다.
volatile은 배타적 수행과는 상관없고 가장 최근에 기록된 값을 읽게 한다.
java.util.concurrent.atomic
패키지의 클래스처럼 lock-free하면서도 thread-safe한 클래스를 사용하자.
그냥 가변 데이터는 단일 쓰레드에서만 써.
동기화 영역 안에서는 외계인 메서드는 절대 금지. 동기화 영역 안에서의 작업을 최대한 줄여라.
가변 클래스에서는 클라이언트에서 알아서 동기화하게 할지, 아니면 thread-safe하게 만들지 고민하자(lock splitting? lock striping? nonblocking concurrency control?).
멀티코어 세상인 지금 과도한 동기화를 피하는 게 어느 때보다 중요하다.
자바 병렬 프로그래밍(에이콘 출판사, 2008) 참조
동시성 수준만큼의 스레드를 생성못하는 경우도 생길 수 있는데 이런 경우를 스레드 기아 교착상태 thread starvation deadlock.
InterruptedException을 캐치하면 Thread.currentThread().interrupt()
관용구를 사용해 인터럽트(interrupt)를 되살린다.
시간 간격을 잴때는 항상 System.nanoTime
wait와 notify는 쓰지마.
- 불변 immutable
- 무조건적 스레드 안전 unconditionally thread-safe: 내부에서 충실히 동기화해서 외부 동기화 불필요
- 조건부 스레드 안전 conditionally thread-safe: 일부 메서드는 외부 동기화 필요
- 스레드 안전하지 않음 not thread-safe: 동시에 사용하려면 외부 동기화 필수
- 스레드 적대적 thread-hostile: 정적 데이터를 아무 동기화없이 수정하는 경우(외부 동기화도 답이 없는 상태)
thread-safe하려면 `synchronized` 메서드가 아닌 비공개 락 객체를 사용하자.
지연 초기화(lazy initialization)이 필요한 경우는 사용 비율이 낮은데 초기화 비용이 큰 경우이다. 하지만 정말 그런지 확인하는 방법이 성능을 측정해보는 방법 밖에 없다. **대부분의 상황에서는 일반적인 초기화가 지연 초기화보다 낫다. **
정적 필드를 지연 초기화해야 한다면 지연 초기화 홀더 클래스(lazy initialization holder class) 관용구.
인스턴스 필드를 지연 초기화해야 한다면 이중검사(double-check) 관용구.
스레드의 평균적인 수를 프로세서 수보다 지나치게 많아지지 않도록 하자.
스레드는 절대 바쁜 대기(busy waiting) 상태가 되면 안된다.