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

설계 검토: 채널 없이 구현하기

지금까지 우리가 걸어온 여정을 잠시 돌아봅시다.

채널 직렬화(Serialization)를 통한 동기화

첫 번째 다중 스레드 티켓 저장소는 다음과 같은 방식이었습니다.

  • 공유 데이터를 관리하며 항상 실행 중인 서버(Server) 스레드 한 개
  • 채널을 통해 요청을 보내는 여러 클라이언트(Client)

서버 스레드만이 데이터에 직접 접근할 수 있었기 때문에, 별도의 잠금이 필요 없었죠. 채널이 들어오는 모든 요청을 **직렬화(Serialization)**하여 한 줄로 세워주었기 때문입니다. 하지만 서버가 한 번에 하나의 요청만 처리할 수 있어 조회의 효율성이 떨어진다는 단점이 있었습니다.

세분화된 잠금(Fine-grained Locking)

그다음 우리는 각 티켓이 개별 잠금을 가지는 더 정교한 구조로 이동했습니다. 클라이언트가 직접 잠금을 획득해 데이터를 읽거나 원자적으로 수정할 수 있게 되었죠.

이 방식은 병렬 처리가 가능해졌지만, 여전히 서버 스레드가 명령을 하나씩 꺼내 잠금을 할당하는 직렬적인 방식에 의존하고 있었습니다. 그렇다면 채널을 아예 없애고 클라이언트가 TicketStore에 직접 접근하게 만들 수는 없을까요?

채널(Channel) 제거하기

채널을 제거하려면 두 가지 숙제를 해결해야 합니다.

  • 여러 스레드 사이에서 TicketStore 공유하기
  • 데이터 접근 동기화하기

스레드 간 TicketStore 공유하기

모든 스레드가 동일한 상태를 바라보게 만들어야 합니다. 우리는 이미 스레드 간에 무언가를 공유할 때 어떤 해결책이 있는지 알고 있죠. 바로 **Arc**를 활용하는 것입니다.

접근 동기화하기

채널이 사라지면 TicketStore 자체에 대한 동기화 문제도 새로 생깁니다. 예전에는 채널 덕분에 티켓을 새로 추가하거나 삭제하는 과정이 자동으로 줄을 섰지만(직렬화), 이제는 저장소 자체에 대한 잠금도 필요하게 된 것이죠.

전체 저장소를 Mutex로 보호한다면 각 티켓마다 RwLock을 두는 것은 큰 의미가 없게 됩니다. 어차피 저장소 잠금이 풀릴 때까지 기다려야 하니까요. 반면에 저장소 전체를 RwLock으로 보호한다면, 티켓 조회는 병렬로 처리하면서 티켓의 삽입/삭제 시에만 모든 작업을 잠시 멈추게 할 수 있습니다.

이제 이 방향으로 코드를 작성하면 어떤 결과가 나오는지 살펴봅시다!

Exercise

The exercise for this section is located in 07_threads/13_without_channels