Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

읽기 및 쓰기(RwLock)

개선된 TicketStore는 잘 작동하지만, 읽기 성능 면에서 아쉬움이 있습니다. Mutex<T>는 읽기 작업(Reader)과 쓰기 작업(Writer)을 구분하지 않기 때문에, 누군가 티켓을 읽고만 있어도 다른 클라이언트들은 그 티켓을 읽기 위해 줄을 서야 하죠.

이런 상황에서는 **읽기-쓰기 잠금(RwLock, Read-Write Lock)**인 RwLock<T>가 훌륭한 대안이 됩니다. RwLock<T>여러 명의 읽기 작업이 동시에 데이터에 접근하는 것을 허용하되, 쓰기 작업은 오직 한 명만 가능하도록 제어합니다.

RwLock<T>에는 잠금을 얻는 두 가지 메서드 readwrite가 있습니다. read는 데이터를 읽을 수 있는 가드를, write는 데이터를 수정할 수 있는 가드를 반환합니다.

use std::sync::RwLock;

// 읽기-쓰기 잠금으로 보호되는 정수형 변수 let lock = RwLock::new(0);

// 첫 번째 읽기 잠금 획득 let guard1 = lock.read().unwrap();

// 첫 번째 잠금이 유지되는 동안에도
// **두 번째** 읽기 잠금을 동시에 얻을 수 있습니다!
let guard2 = lock.read().unwrap();

장단점

얼핏 보면 RwLock<T>Mutex<T>의 모든 기능을 포함하면서 더 좋아 보입니다. 그렇다면 왜 항상 RwLock<T>만 쓰지 않고 Mutex<T>를 함께 사용할까요?

여기에는 두 가지 주요 이유가 있습니다.

  • 성능 비용: RwLock<T>Mutex<T>보다 잠금을 거는 비용이 더 큽니다. 현재 읽기 작업과 쓰기 작업이 각각 몇 개인지 계속 추적해야 하기 때문이죠. 만약 쓰기 작업이 읽기 작업만큼 많다면 오히려 Mutex<T>가 더 효율적일 수 있습니다.
  • 쓰기 작업 기아 현상(Writer Starvation): 끊임없이 읽기 요청이 들어온다면 쓰기 작업은 잠금을 얻을 기회를 영영 잡지 못할 수도 있습니다. 이를 ’기아 현상’이라고 부릅니다. RwLock<T>은 잠금 획득 순서를 보장하지 않으며, 이는 운영체제의 정책에 따라 달라질 수 있습니다.

우리의 티켓 시스템처럼 대다수의 클라이언트가 조회를 주로 하고 수정은 가끔 하는 읽기 위주의 환경에서는 RwLock<T>가 아주 탁월한 선택이 될 것입니다.

Exercise

The exercise for this section is located in 07_threads/12_rw_lock