[RUST] 러스트 프로그래밍 공식 가이드(제2판) 16장 요약
겁 없는 동시성
- 소유권과 타입 검사를 지렛대 삼음으로써, 많은 동시성 에러가 컴파일 타임 에러가 됨
스레드를 이용하여 코드를 동시에 실행하기
- 스레드 : 프로그램 내에서 동시에 실행되는 독립적인 부분들을 실행하는 기능
spawn으로 새로운 스레드 생성하기
- 새로운 스레드를 생성하기 위해서는
thread::spawn
함수를 호출하고 여기에 새로운 스레드에서 실행하고 싶은 코드가 담긴 클로저를 넘김 - 메인 스레드가 완료되면 생성된 모든 스레드는 실행이 종료되었든 혹은 그렇지 않든 멈추게 됨
thread::sleep
의 호출은 스레드의 실행을 강제로 잠깐 멈추게 하는데, 다른 스레드는 실행될 수 있도록 함
join 핸들을 사용하여 모든 스레드가 끝날 때까지 기다리기
thread::spawn
의 반환 타입인JoinHandle
은 자신의join
메서드를 호출하면 해당 스레드가 끝날 때 까지 기다림
스레드에 move 클로저 사용하기
thread::spawn
은 새 스레드에서 클로저를 실행하는 함수인데, 이 클로저가 외부 변수를 캡처할 경우 메인 스레드의 생명주기와 달라 외부 변수가 더 이상 유효하지 않을 수 있는데 이를 해결하기 위해 move 클로저를 사용하여 외부 변수의 소유권을 클로저로 이동시키며thread::spawn(move || ...)
와 같이 사용됨
메시지 패싱을 사용하여 스레드 간 데이터 전송하기
- 메시지 패싱이란 스레드 간 데이터를 직접 공유하지 않고, 메시지를 주고받는 방식으로 통신하는 방법을 말함
- 채널 : 한 스레드에서 다른 쪽으로 데이터를 보내기 위한 일반적인 프로그래밍 개념
- 메시지 보내기 동시성을 달성하기 위해 러스트 표준 라이브러리는 채널(channel) 구현체를 제공함
- 송신자(tx, transmitter)와 수신자(rx, receiver)로 구성
- mspc(multiple producer, single consumer) 는 복수 생산자와, 단일 소비자를 나타내며 mpsc::channel 함수는 튜플을 반환하는데 첫번째 요소는 송신 단말, 두번째 요소는 수신 단말을 나타냄 (
(tx, rx)
) send
메서드 : 송신자가 데이터를 채널에 보낼 때 사용하며Result<T,E>
타입을 반환함 (수신자가 닫혀있으면 에러 반환)recv
메서드 : 수신자가 채널로부터 데이터를 기다리고 받을 때 사용하며Result<T,E>
타입을 반환함 (송신자가 닫히면 에러 반환)try_recv
메서드 : 메시지가 있으면 즉시 반환하고, 없으면 Err 를 반환하며Result<T,E>
타입을 반환
채널과 소유권 이동
- 채널(mpsc::channel)로 값을 보낼 때
send
메서드는 소유권을 가져가는데, 이는send(val)
를 호출한 뒤 보내진 val 을 양쪽 스레드에서 동시에 접근할 수 있다면 데이터 경쟁이 발생할 수 있기 때문에 러스트는 이런 위험을 컴파일 타임에 차단함
공유 상태 동시성
뮤텍스
- 뮤텍스(mutex)는 상호 배제(mutual exclusion)의 줄임말로, 뮤텍스에서는 한 번에 하나의 스레드만 데이터 접근을 허용함
- 뮤텍스의 두 가지 규칙
- 데이터를 사용하기 전에는 반드시 락을 얻는 시도를 해야 함
- 뮤텍스가 보호하는 데이터의 사용이 끝나면 반드시 언락을 해야 다른 스레드들이 락을 얻을 수 있음
- Mutex
에는 **교착 상태**를 생성할 위험성이 있음 - 교착상태 예시
1 2 3
테이블에 숟가락과, 포크가 있고 숟가락, 포크를 모두 얻어야 식사를 할 수 있는데, 두 사람이 각각 숟가락과 포크를 하나씩 나눠 가져간 경우, 테이블에는 아무것도 존재하지 않아 무한히 대기하는 상황이 발생됨
- 교착상태 예시
Mutex의 API
- Mutex
는 스마트 포인터이며, 연관 함수 `new` 를 사용하여 만들어짐 - 뮤텍스 내의 데이터에 접근하기 위해서는
lock
메서드를 사용하여 락을 획득 - 락을 보유 중인 스레드가 패닉을 발생하면, 그 락은 손상 상태가 되어 이후의
lock
호출은Err
를 반환 lock
은MutexGuard
라는 스마트 포인터를 반환하는데 이 타입은Deref
를 구현하여*guard
로 내부 값 접근이 가능하며 또한Drop
도 구현되어 있어 스코프를 벗어나면 자동으로Drop
되어 락이 해제됨
Arc를 이용한 아토믹 참조 카운팅
Arc<T>
는 스레드 간 안전하게 공유 가능한Rc<T>
같은 타입- “A”는 Atomic(원자적) 을 의미하며, 참조 카운트를 원자적 연산으로 증가/감소시켜 여러 스레드에서 동시에 접근해도 데이터 경쟁 없이 안전함
This post is licensed under CC BY 4.0 by the author.