C.W.K.
Stream
Lesson 03 of 05 · published

채널 — 메시지 패싱

~11 min · concurrency, channels, mpsc

Level 0Rust 호기심러
0 XP0/80 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete

스레드가 협력하는 한 방법은 메모리 공유 대신 메시지를 패싱 하는 거야. Rust 의 표준 채널 — mpsc — 은 한 스레드가 다른 스레드로 값을 보내게 해, 가는 길에 소유권이 이전되면서.

mpsc: 여러 producer, 단일 consumer

mpsc::channel()(Sender, Receiver) 쌍을 반환해. Sender 를 든 스레드가 .send(value) 를 부르고; Receiver 를 든 스레드가 .recv() (블로킹) 를 부르거나 순회해. 'mpsc' = 여러 sender, 한 receiver: Sender 를 clone 해서 여러 스레드에서 한 receiver 를 먹일 수 있어.

send 는 소유권을 이전해

값을 send 하면 소유권이 채널로 그다음 receiver 로 move 해 — sender 는 그 뒤 못 써. 또 그 move 시맨틱이고, 그게 채널이 race-free 인 이유야: 값은 한 번에 한쪽만 소유. 공유 가변 상태가 없으면 락도 데이터 레이스도 없어.

'메모리를 공유해 소통하지 말고; 소통해서 메모리를 공유하라.' 채널은 스레드 간 소유권을 move 해서, 어느 순간이든 한 스레드만 값을 들어. 락보다 추론하기 종종 더 단순해 — 보호할 공유 상태 없이, 그냥 한 방향으로 흐르는 값들.

채널 vs 공유 상태

유효한 두 스타일: 메시지 패싱 (채널, 이 레슨) 과 공유 상태 (Arc<Mutex>, 다음 레슨). 채널은 파이프라인이랑 producer/consumer 셋업에 맞아 — 데이터가 한 방향으로 흘러. 공유 상태는 여러 스레드가 한 구조를 읽고 갱신하는 데 맞아. 진짜 프로그램은 둘 다 섞어; 어느 게 문제에 맞는지 아는 게 기술이야.

Code

여러 producer 가 한 receiver 를 먹인다·rust
use std::sync::mpsc;
use std::thread;

fn main() {
    let (tx, rx) = mpsc::channel();

    // producer spawn; 각 send 가 소유권을 채널로 이전
    for id in 0..3 {
        let tx = tx.clone(); // 스레드마다 Sender clone (multiple producer)
        thread::spawn(move || {
            tx.send(format!("hello from {id}")).unwrap();
        });
    }
    drop(tx); // 원본을 drop 해서 producer 끝나면 채널이 닫히게

    // receiver 는 모든 sender 가 사라질 때까지 순회
    for msg in rx {
        println!("{msg}");
    }
}

External links

Exercise

producer/consumer 를 지어: 워커 스레드 4개가 각각 자기 id 제곱을 채널로 보내고, main 이 모든 결과를 Vec 으로 모아 합산하게. receiver 루프가 종료되게 해 — 그러려면 sender 를 어떻게 해야 해?
Hint
각 워커에 sender 를 clone 하고 spawn 후 main 의 원본 tx 를 drop 해. for msg in rx 루프는 마지막 sender (마지막 워커의 clone) 가 drop 될 때 끝나.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 똘이warm

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.