🔄
스레드와 채널 — 소유권 기반 동시성
"메모리를 공유해서 통신하지 말고, 통신해서 메모리를 공유하라"
동시성 프로그래밍에서 가장 무서운 건 data race다. 두 스레드가 같은 메모리를 동시에 쓰면 정의되지 않은 동작(undefined behavior)이 발생한다.
Rust에서는 이게 컴파일 에러다. &mut T가 하나만 존재할 수 있다는 규칙이 스레드 경계에서도 적용되기 때문. Send/Sync trait이 타입이 스레드 간에 안전하게 이동/공유할 수 있는지를 컴파일 타임에 검증한다.
채널 (mpsc)
let (tx, rx) = mpsc::channel();
thread::spawn(move || { tx.send(42).unwrap(); });
println!("received: {}", rx.recv().unwrap());
move 클로저로 소유권을 스레드에 넘긴다. 보낸 쪽은 더 이상 그 값을 쓸 수 없다.
Mutex
let counter = Arc::new(Mutex::new(0));
// 각 스레드에서 Arc::clone으로 공유
Mutex는 한 번에 하나의 스레드만 데이터에 접근하게 한다. Arc로 감싸서 여러 스레드에서 공유한다.
핵심 포인트
1
std::thread::spawn으로 OS 스레드 생성
2
move 클로저로 데이터 소유권을 스레드에 이전
3
mpsc::channel()로 메시지 패싱 (소유권 이동 기반)
4
Arc<Mutex<T>>로 공유 가변 상태 보호
장점
- ✓ data race가 컴파일 에러 — 런타임 동시성 버그 원천 차단
- ✓ Send/Sync trait으로 스레드 안전성을 타입으로 보장
단점
- ✗ Mutex 데드락은 컴파일러가 못 잡는다
- ✗ Arc<Mutex> 보일러플레이트가 다른 언어보다 무겁다
사용 사례
병렬 데이터 처리 — Rayon crate로 이터레이터를 자동 병렬화
웹 서버 — 요청별 스레드 + 공유 상태(DB 풀 등)