Abseil Tip 197 Reader Lock은 드물게 사용해야 합니다

제목: “이번 주의 팁 #197: Reader Lock은 드물게 사용해야 합니다”

원문 게시일: 2021년 7월 29일
업데이트: 2024년 4월 1일

작성자: Titus Winters

빠른 링크: abseil.io/tips/197


Reader Lock이란?

absl::Mutex 클래스는 두 가지 잠금 방식을 지원합니다:

  1. 배타적 잠금 (Exclusive Lock): 한 번에 하나의 스레드만 잠금을 가질 수 있습니다.
  2. 공유 잠금 (Shared Lock): 두 가지 모드로 작동합니다.
    • 쓰기 모드: 배타적 잠금을 사용합니다.
    • 읽기 모드: 여러 스레드가 동시에 잠금을 가질 수 있습니다.

공유 잠금이 유용한 이유는 여러 스레드가 데이터에 대해 읽기 전용 작업을 수행할 때 경쟁 상태를 줄이고 동기화 문제를 방지할 수 있기 때문입니다.

absl::MutexMutex::Lock()(또는 동일한 동작을 하는 Mutex::WriterLock())과 Mutex::ReaderLock()을 제공합니다. 이를 보면, 데이터를 읽기만 하는 경우에는 ReaderLock()을 사용하는 것이 더 나아 보일 수 있습니다. 하지만 대부분의 경우, 이는 잘못된 선택입니다.


Reader Lock의 문제점

1. Reader Lock은 느리다

ReaderLock()은 배타적 잠금보다 더 많은 부가 작업과 오버헤드를 요구합니다.
결과적으로, 짧은 임계 구역(critical section)에서는 공유 잠금을 사용하는 것이 오히려 성능을 저하시키는 경우가 많습니다. 경쟁 상태가 없는 경우에는 공유 잠금의 이점도 크게 줄어듭니다.

배타적 잠금과 공유 잠금의 차이점:

  • 배타적 잠금은 단순히 하나의 스레드만 접근 가능하도록 보장합니다.
  • 공유 잠금은 읽기-쓰기 모드를 구분하며, 다른 스레드의 읽기/쓰기 상태를 확인하고 관리해야 합니다.

이로 인해 공유 잠금은 더 복잡하며, 경쟁 상태가 발생할 경우 성능 저하가 심해질 수 있습니다.


2. 언제 공유 잠금이 유용한가?

공유 잠금은 잠금을 오래 유지해야 하며 여러 스레드가 동시에 공유 잠금을 사용할 가능성이 높을 때 유용합니다.
예를 들어, 큰 컨테이너를 반복 처리하거나 복잡한 계산이 필요한 경우 공유 잠금이 적합할 수 있습니다.

그러나 잠금을 짧게 유지하는 단순 조회의 경우, 공유 잠금은 추가적인 복잡성과 비용을 초래합니다.

// 나쁜 예제: 짧은 임계 구역에서 Reader Lock 사용
int Foo::GetElementSize() const {
  absl::ReaderMutexLock l(&lock_);
  return element_size_;
}

위 코드는 element_size_ 값을 단순히 조회하기 위해 공유 잠금을 사용합니다.
그러나 잠금 관리의 부가 비용이 실제 데이터 접근보다 크기 때문에 성능이 떨어질 수 있습니다.


3. 대안적인 접근법

공유 잠금이 유용한 경우에도, 경쟁 상태를 완전히 피하는 더 나은 방법을 종종 찾을 수 있습니다.
예를 들어:

  • RCU(Read-Copy-Update) 방식은 읽기 경로를 사실상 무료로 만듭니다.
  • 빠른 조회를 위해 동기화 자체를 줄이는 특수화된 인터페이스를 사용할 수 있습니다.

올바른 접근법

1. Reader Lock 사용을 주의 깊게 검토하라

코드에서 ReaderLock()을 발견하거나 새로 작성하려는 경우, “이 잠금이 오래 유지될 가능성이 있는가?”라는 질문을 던져야 합니다.

  • 단순 조회라면, 배타적 잠금(Lock)이 더 나은 선택일 가능성이 높습니다.

2. 성능 분석 활용

Reader Lock의 유효성은 상황에 따라 달라질 수 있습니다.
프로파일링 도구를 사용하여 경쟁 상태와 잠금 유지 시간을 측정하고, Reader Lock이 실제로 성능에 기여하는지 확인해야 합니다.


결론

ReaderLock()은 특정 상황에서 유용할 수 있지만, 대부분의 경우 배타적 잠금이 더 적합합니다.
특히 짧은 임계 구역에서는 Reader Lock의 복잡성과 비용이 실제 이점보다 클 가능성이 큽니다.

Reader Lock을 사용하기 전에 경쟁 상태, 임계 구역 길이, 잠금 유지 시간을 평가하고, 가능한 경우 RCU나 다른 비동기화 기법을 고려하세요.