Effective Java를 읽고 정리한 정리본입니다.

📌 Item 79 : 과도한 동기화는 피하라

아이템 78에서는 충분하지 못한 동기화로 인해 생기는 문제점에 대해 다뤘다.

volatile, synchronized 키워드를 통해 살펴보았는데, 이를 제대로 해주지 않으면 동기화에 문제가 생겨 데이터 일관성이 깨진다는 것이다.

그러나 너무 과도하게 동기화를 해도 문제가 발생한다.

🫧 클라이언트에 양도하지 말아라

응답 불가와 안전 실패를 피하기 위해서는 동기화 메서드나 동기화 블록 안에서 제어를 절대 클라이언트에 양도하면 안 된다.

  1. 동기화된 영역 안에서는 재정의할 수 있는 메서드를 호출해서는 안 된다.
  2. 클라이언트가 넘겨준 함수 객체를 호출해서도 안 된다.

이렇듯, 동기화된 영역을 포함한 클래스 관점에서는 외부에서 온 메서드는 무슨 일을 할지 알지 못하며, 통제할 수 없기 때문에 흔히 외계인 메서드라고 불린다.

외계인 메서드가 하는 일에 따라 동기화된 영역은 예외를 일으키거나, 교착 상태에 빠지거나, 데이터를 훼손할 수도 있다.

따라서, 외계인 메서드는 동기화 바깥으로 옮겨야 한다.

🫧 CopyOnWriteArrayList

CopyOnWrite는 변경 사항이 있을 시 복사본을 만들어 수정 후 해당 부분을 가리키도록 하는 알고리즘이다.

내부를 변경한느 작업은 항상 깨끗한 복사본을 만들어 수행하도록 구현함으로써, 내부의 배열이 수정이 되지 않도록 막아 순회 시 락이 필요 없어 빠르다는 장점이 있다.

위와 같은 상황을 막기 위해서는, 동기화 영역에서는 꼭 필요한 일들만 수행해야 한다.

🫧 가변 클래스 작성 시 주의 사항

  1. 동기화를 전혀 사용하지 말고, 그 클래스를 동시에 사용해야 하는 클래스가 외부에서 알아서 동기화하게 만들자.
  2. 동기화를 내부에서 수행해 스레드 안전한 클래스로 만들자.

🫧 클래스 내부 동기화 방법

  1. 락 분할 (lock splitting)
  2. 락 스트라이핑 (lock striping)
  3. 비차단 동시성 제어 (nonblocking concurrency control)