ReadWriteLock — 읽기/쓰기 락

ReadWriteLock — 읽기/쓰기 락

ReadWriteLock읽기 전용 연산용 락과 쓰기용 락 한 쌍을 유지하는 락이에요. 읽기 락은 작가(writer)가 없는 동안 여러 독자(reader) 스레드가 동시에 보유할 수 있고, 쓰기 락은 독점적이에요.

출처: Java API Reference

본문

개념 이해하기

ReadWriteLock은 읽기 전용 연산용 락과 쓰기용 락 한 쌍을 유지해요. 읽기 락은 작가가 없는 동안 여러 독자가 동시에 보유할 수 있고, 쓰기 락은 독점이에요.

public interface ReadWriteLock

모든 구현은 writeLock 연산의 메모리 동기화 효과(Lock 인터페이스에 명시)가 연관 readLock에도 적용되도록 보장해야 해요. 즉, 읽기 락을 성공적으로 획득한 스레드는 쓰기 락의 이전 해제 시 이루어진 모든 업데이트를 보게 돼요.

읽기-쓰기 락은 상호 배제 락보다 더 높은 수준의 동시성을 허용해요. 단일 스레드만 공유 데이터를 수정할 수 있지만, 많은 경우 임의 개수의 스레드가 동시에 데이터를 읽을 수 있다는 사실을 활용해요.

성능 고려 사항

실제로 이 동시성 증가는 다중 프로세서에서, 그리고 공유 데이터의 접근 패턴이 적합할 때만 완전히 실현돼요. 읽기-쓰기 락이 상호 배제 락보다 성능을 개선할지는 다음에 달려 있어요:

  • 데이터가 읽히는 빈도 vs 수정되는 빈도
  • 읽기·쓰기 연산의 지속 시간
  • 데이터에 대한 경합(동시에 읽거나 쓰려는 스레드 수)

예를 들어 처음 데이터로 채워진 뒤 자주 수정되지 않고 빈번히 검색되는 컬렉션(예: 어떤 종류의 디렉토리)은 이상적인 후보예요. 그러나 업데이트가 잦아지면 데이터가 대부분 독점 락 상태로 지내 동시성 증가가 거의 없어요. 또한 읽기 연산이 너무 짧으면 구현 오버헤드가 실행 비용을 지배할 수 있어요. 결국 프로파일링과 측정이 판단을 내려요.

정책 결정

구현이 해야 할 여러 정책 결정이 있어요:

  • 작가가 쓰기 락을 해제할 때 독자와 작가가 모두 기다릴 경우 읽기 락과 쓰기 락 중 무엇을 부여할지. 작가 선호가 흔해요(쓰기는 짧고 드물 것이 기대되므로).
  • 독자가 활성이고 작가가 대기 중일 때 독자를 렌더하는지 — 독자 선호는 작가를 무기한 지연시킬 수 있어요.
  • 락이 재진입(reentrant) 적인지 — 쓰기 락 보유자가 재획득할 수 있는지, 쓰기 락을 보유하면서 읽기 락을 얻을 수 있는지.
  • 쓰기 락이 개입하는 작가 없이 읽기 락으로 다운그레이드될 수 있는지, 읽기 락이 쓰기 락으로 업그레이드될 수 있는지.

메서드

Lock readLock() — 읽기에 쓰는 락을 반환해요.

Lock writeLock() — 쓰기에 쓰는 락을 반환해요.

대표 구현체는 ReentrantReadWriteLock이에요.

더 알아보기 (Learn more)