티스토리 뷰

스레드 안전성

  • 멀티스레드 환경에서도 API를 안전하게 사용하게 하려면 클래스가 지원하는 스레드 안전성 수준을 정확히 명시해야 한다

스레드 안정성 높은 순

  • 불변(immutable): 이 클래스의 인스턴스는 마치 상수와 같아서 외부 동기화도 필요 없다.String,Long,Biglnteger

  • 무조건적 스레드 안전(unconditionally thread-safe):이 클래스의 인스턴스
    는 수정될 수 있으나,내부에서 충실히 동기화하여 별도의 외부 동기화 없이 동시에 사용해도 안전하다. AtomicLong, ConcurrentHashMap이 여기에 속한다.

  • 조건부 스레드 안전(conditionally thread-safe):무조건적 스레드 안전과 같으나,일부 메서드는 동시에 사용하려면 외부 동기화가 필요하다.

  • Collections.synchronized* 래퍼 메서드가 반환한 컬렉션들이 여기 속한다
    (이 컬렉션들이 반환한 반복자는 외부에서 동기화해야 한다).

  • 스레드 안전하지 않음(not thread-safe):이 클래스의 인스턴스는 수정될 수
    있다. 동시에 사용하려면 각각의(혹은 일련의) 메서드 호출을 클라이언트가
    선택한 외부 동기화 메커니즘으로 감싸야 한다. ArrayList, HashMap 같은 기본 컬렉션이 여기 속한다.

  • 스레드 적대적(thread-hostile): 이 클래스는 모든 메서드 호줄을 외부 동기화로 감싸더라도 멀티스레드 환경 에서 안전하지 않다. 이 수준의 클래스는 일반적으로 정적 데이터를 아무 동기화 없이 수정한다. 이런 클래스를 고의로 만드는 사람은 없겠지만,동시성을 고려하지 않고 작성하다 보면 우연히 만들어질 수 있다. 스레드 적대적으로 밝혀진 클래스나 메서드는 일반적으로 문제를 고쳐 재배포하거나 사용 자제(deprecated) API로 지정한다.

  • 클래스의 스레드 안전성은 보통 클래스의 문서화 주석에 기재하지만,독특한 특성의 메서드라면 해당 메서드의 주석에 기재하도록 하자

  • 내부에서 처리하는 고성능 동시성 제어 메커니즘과 혼용할 수 없게 되는 것이다. 그래서 ConcurrentHashMap 같은 동시성 컬렉션과는 함께 사용하지 못 한다

  • 또한,클라이언트가 공개된 락을 오래 쥐고 놓지 않는 서비스 거부 공격 (denial-of-service attack)을 수행할 수도 있다

  • 서비스 거부 공격을 막으려면 synchronized 메서드(이 역시 공개된 락이나 마찬가지다) 대신 비공개 락 객체를 사용해야 한다.

private final Object lock = new ObjectO; 
public void fooO {
    synchronized(lock) { 
    }
}
  • 비공개 락 객체는 클래스 바깥에서는 볼 수 없으니 클라이언트가 그 객체의 동기화에 관여할 수 없다. 락 객체를 동기화 대상 객체 안으로 캡슐화한 것이다.

핵심 정리

모든 클래스가 자신의 스레드 안전성 정보를 명확히 문서화해야 한다.정확한 언어로 명 확히 설명하거나 스레드 안전성 애너테이션을 사용할 수 있다.
synchronized한정자는 문서화와 관련이 없다.조건부 스레드 안전 클래스는 메서드를 어떤 순서로 호출할 때 외 부 동기화가 요구되고,그때 어떤 락을 얻어야 하는지도 알려줘야 한다.무조건적 스레드 안전 클래스를 작성할 때는 synchronized 메서드가 아닌 비공개 락 객체를 사용하자
이렇게 해야 클라이언트나 하위 클래스에서 동기화 메커니즘을 깨뜨리는 걸 예방할 수 있고,필요하다면 다음에 더 정교한 동시성을 제어 메커니즘으로 재구현할 여지가 생긴다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함