Locking To Read

  • 공유 리소스에 대한 읽기 작업을 보호하기 위해서 잠금을 사용하는 것을 의미한다.
  • 멀티쓰레드 환경에서 데이터 일관성르 보장하고 경쟁 조건 방지하기 위해서 사용된다.
  • 읽기 작업에 불필요하게 잠금을 하면 병목 포인트가 된다.

문제점

  • 읽기 잠금을 획득하면 다른 쓰레드에서 해당 리소스를 읽지 못한다.
  • 불필요한 경합으로 직렬화되면 성능이 저하되고 지연 시간이 늘어날 수 있다.
  • 올바르게 구현하지 않으면 교착 상태가 발생할 수도 있다.
  • 동시성 감소
  • 잠재적 교착 상태
  • 오버헤드
  • 코드 복잡성

대체 접근 방식

읽기·쓰기 잠금

  • 읽기/쓰기 잠금은 여러 쓰레드가 동시에 리소스를 읽으면서 동시에 쓰기 전용 액세스를 보장하는 동기화 메커니즘
  • 이를 통해서 작업 성능 향상을 할 수 있다.

불변 데이터 사용

  • 대안으로 불변 데이터를 사용한다.
  • 수정할 수 없으므로 쓰레드에 안전하다.

캐싱

  • 자주 액세스하는 데이터를 메모리에 캐싱해서 공유 리소스에 대한 읽기 작업 접근 횟수를 최소화할 수 있다.
  • ReadWriteLock
  • 불변 데이터 구조
  • 휘방성 변수 : 자주 읽지만 거의 수정하지 않는 단순한 변수를 다룰 때 volatile을 사용하면 잠금 없이도 쓰레드 전체에 변경 사항을 확인할 수 있다.
  • 더 높은 수준의 동기화 메커니즘 : 원자 변수, 동시 컬렉션, CountDownLatch, CyclicBarrier 등

개선안

  • 세분화된 잠금 사용
  • 읽기 최적화
  • 중첩 잠금 피하기
  • 잠금 경합을 모니터링
  1. 공유 데이터를 읽기 위해서 잠금이 사용되는 코드 섹션 식별
  2. 데이터 액세스 패턴을 평가하고 읽기가 쓰기보다 많은지 확인
  3. 여러 쓰레드가 동시에 공유 데이터를 읽을 수 있도록 독점 잠금을 ReadWriteLock으로 대체
  4. 공유 데이터를 변경 불가하게 만들거나 자바 동시성 유틸리티에서 제공하는 상위 수준의 동기화 메커니즘을 사용하도록 코드 리펙토링

읽기 잠금을 피하려면?

  • ConcurrentHashMap
  • CopyOnWriteArrayList