채널
Rust는 스레드 간 통신을 위한 비동기 채널(channels)을 제공합니다. 채널은 Sender와 Receiver라는 두 끝점 사이에서 정보의 단방향 흐름을 가능하게 합니다.
use std::sync::mpsc::{Sender, Receiver};
use std::sync::mpsc;
use std::thread;
static NTHREADS: i32 = 3;
fn main() {
// 채널에는 두 끝점이 있습니다: `Sender<T>`와 `Receiver<T>`.
// 여기서 `T`는 전송될 메시지의 타입입니다
// (타입 어노테이션은 불필요합니다)
let (tx, rx): (Sender<i32>, Receiver<i32>) = mpsc::channel();
let mut children = Vec::new();
for id in 0..NTHREADS {
// 발신자(sender) 끝점은 복사될 수 있습니다
let thread_tx = tx.clone();
// 각 스레드는 채널을 통해 자신의 id를 보낼 것입니다
let child = thread::spawn(move || {
// 스레드가 `thread_tx`에 대한 소유권을 가져갑니다
// 각 스레드는 채널에 메시지를 큐에 넣습니다
thread_tx.send(id).unwrap();
// 보내기는 비차단(non-blocking) 연산이므로, 스레드는
// 메시지를 보낸 직후 계속 실행됩니다
println!("{}번 스레드 종료", id);
});
children.push(child);
}
// 여기서 모든 메시지가 수집됩니다
let mut ids = Vec::with_capacity(NTHREADS as usize);
for _ in 0..NTHREADS {
// `recv` 메서드는 채널에서 메시지를 하나 꺼냅니다
// `recv`는 사용 가능한 메시지가 없으면 현재 스레드를 차단(block)합니다
ids.push(rx.recv());
}
// 스레드들이 남은 작업을 모두 완료할 때까지 기다립니다
for child in children {
child.join().expect("이런! 자식 스레드에서 패닉이 발생했습니다");
}
// 메시지가 전송된 순서를 보여줍니다
println!("{:?}", ids);
}