제목: (멀티 코어를 100% 활용하는) 자바 병렬 프로그래밍 / Java Concurrency in Practice

저자: 브라이어 게츠, 더그 리, 팀 피얼스, 조셉 보우비어, 데이빗 홈즈, 조슈아 블로쉬

출판사: 에이콘


스레드 안전한 객체를 만드는 방법.


4.2 인스턴스 한정

공유 데이터를 객체 내부에 숨겨두고, 이를 관리하는 부분에 락을 적용한다.

ArrayList나 Hashmap은 스레드 안전하지 않지만, Collections.synchronizedList와 같은 API로 생성한 컬렉션은 스레드 안전하다. 이는 래퍼 클래스를 거쳐야만 컬렉션 클래스의 내용을 사용할 수 있기 때문이다.


4.3 스레드 안정성 위임

스레드 안전성이 확보된 필드로만 구성된 클래스는 스레드에 안전할 수도 그렇지 않을 수도 있다.

여러 개의 필드가 서로 독립적(필드들이 서로의 상태 값에 대해 연관성이 없음)이 아닐 경우 문제가 된다.

클래스가 서로 의존성 없이 독립적이고 스레드 안전한 두 개 이상의 클래스(필드)를 조합해 만들어져 있고 두 개 이상의 클래스(필드)를 한번에 처리하는 복합 연산 메소드가 없는 상태라면, 스레드 안정성을 필드에 모두 위임할 수 있다.


4.4 스레드 안전하게 구현된 클래스에 기능 추가

스레드 안전한 클래스를 확장해서 사용할 경우 스레드 안정성을 확보하는 방법


4.4.1 호출하는 측의 동기화

아래 ListHelper클래스 처럼 list 객체에 락을 걸어야 쓰레드 안전하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
public calss ListHelper<E> {
    public List<E> list = Collections.synchronizedList(new ArrayList<E>());
    ...
    public boolean putIfAbsent(E x) {
        synchronized(list) {
            boolean absent = !list.contains(x);
            if (absent) {
                list.add(x);
            }
            return absent;
        }
    }
}

putIfAbsent 메소드 자체에 synchronized 키워드만 붙인다고 해서 동기화된 list 객체에서 사용하는 lock과 동일한 lock을 사용하는 것이 아니기 때문이다.
자바 API 문서에 따르면 Collections.synchronizedList에서 반화하는 list객체를 이용하여 lock을 사용해야 한다고 명시되어 있다.

4.5 동기화 정책 문서화

적어도 @GuardedBy annotation (Java 1.5부터 지원)을 이용하여 어느 변수가 동기화되는지라도 표기해 두자.


저작자 표시 비영리 변경 금지
신고

티스토리 툴바