Learn Rust Coding · 강의

Crossbeam 채널

고급 채널

레슨 4/413개 단계

Crossbeam 채널은(는) CoddyKit의 무료 Learn Rust Coding 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Learn Rust Coding 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Learn Rust Coding 강의에는 총 4개의 강의가 포함되어 있습니다.

표준 mpsc를 넘어서

표준 mpsc 채널은 단일 소비자 방식으로 수신자가 하나뿐입니다. crossbeam-channel 크레이트는 더 많은 기능과 대체로 더 나은 성능을 갖춘 다중 생산자, 다중 소비자(mpmc) 채널을 제공합니다.

주요 특징은 다음과 같습니다.

  • 송신자뿐 아니라 복제할 수 있는 Receiver도 제공합니다.
  • 여러 채널을 기다릴 수 있는 강력한 select! 매크로를 제공합니다.
  • 제한된 채널, 제한되지 않은 채널, 틱과 같은 특수 채널을 제공합니다.

의존성 추가하기

Crossbeam은 외부 크레이트이므로 Cargo.toml에 추가해야 합니다.

[dependencies]
crossbeam-channel = "0.5"

그런 다음 해당 함수들을 가져옵니다. Cargo와 외부 크레이트가 필요하므로 여기의 예제는 독립적으로 실행하기보다는 API를 보여 주기 위한 것입니다.

// Cargo.toml
// [dependencies]
// crossbeam-channel = "0.5"

use crossbeam_channel::unbounded;

fn main() {
    let (s, r) = unbounded();
    s.send("hello").unwrap();
    println!("{}", r.recv().unwrap());
}

제한 없음과 제한 있음

Crossbeam은 두 가지 주요 생성 함수를 제공합니다.

  • unbounded()는 필요에 따라 커지며 send가 차단되지 않습니다.
  • bounded(cap)은 고정된 버퍼를 사용하며, 가득 차면 send가 차단되어 역압을 제공합니다.

bounded(0) 채널은 송신과 수신이 직접 값을 넘겨주는 랑데부 채널입니다.

use crossbeam_channel::bounded;
use std::thread;

fn main() {
    let (s, r) = bounded(2);
    thread::spawn(move || {
        for i in 1..=3 {
            s.send(i).unwrap();
        }
    });
    while let Ok(v) = r.recv() {
        println!("got {}", v);
    }
}

여러 소비자

핵심 장점은 Receiver를 복제할 수 있다는 것입니다. 여러 작업 스레드가 같은 채널에서 가져올 수 있으며, 각 메시지는 그중 정확히 하나의 스레드로 전달됩니다. 이것이 작업 훔치기 스레드 풀의 기반입니다.

use crossbeam_channel::unbounded;
use std::thread;

fn main() {
    let (s, r) = unbounded();
    let mut workers = vec![];
    for id in 0..3 {
        let rx = r.clone();
        workers.push(thread::spawn(move || {
            while let Ok(job) = rx.recv() {
                println!("worker {} got job {}", id, job);
            }
        }));
    }
    for job in 0..6 { s.send(job).unwrap(); }
    drop(s);
    for w in workers { w.join().unwrap(); }
}

select! 매크로

select!를 사용하면 한 스레드가 여러 채널 작업을 기다리다가 가장 먼저 준비된 작업을 처리할 수 있습니다. 채널 이벤트에 대한 match와 비슷하며, 여러 원본에서 입력을 결합할 때 적합합니다.

use crossbeam_channel::{unbounded, select};
use std::thread;

fn main() {
    let (s1, r1) = unbounded();
    let (s2, r2) = unbounded();
    thread::spawn(move || { s1.send("from one").unwrap(); });
    thread::spawn(move || { s2.send("from two").unwrap(); });
    for _ in 0..2 {
        select! {
            recv(r1) -> msg => println!("r1: {}", msg.unwrap()),
            recv(r2) -> msg => println!("r2: {}", msg.unwrap()),
        }
    }
}

select!으로 시간 제한 사용하기

select!은 default 분기와 recv(after(duration)) 타이머 분기를 지원합니다. 따라서 영원히 차단되는 대신 시간 제한이 지나면 기다리기를 포기할 수 있습니다. 이는 반응성이 중요한 시스템에 필수적입니다.

use crossbeam_channel::{unbounded, select, after};
use std::time::Duration;

fn main() {
    let (_s, r) = unbounded::<i32>();
    select! {
        recv(r) -> msg => println!("received {:?}", msg),
        recv(after(Duration::from_millis(100))) -> _ => {
            println!("timed out waiting for a message");
        }
    }
}

try_send와 try_recv

표준 라이브러리와 마찬가지로 Crossbeam은 차단되지 않는 변형을 제공합니다. 제한된 채널이 가득 차 있으면 try_send가 즉시 실패하고, 준비된 메시지가 없으면 try_recv가 즉시 실패합니다. 두 함수 모두 상황에 맞춰 처리할 수 있는 구체적인 오류를 반환합니다.

use crossbeam_channel::{bounded, TrySendError};

fn main() {
    let (s, _r) = bounded(1);
    s.send(1).unwrap();
    match s.try_send(2) {
        Ok(()) => println!("sent"),
        Err(TrySendError::Full(v)) => println!("full, kept {}", v),
        Err(TrySendError::Disconnected(v)) => println!("closed, kept {}", v),
    }
}

tick과 주기적 작업

tick(duration) 함수는 일정한 간격으로 메시지를 전달하는 수신자를 반환합니다. 이를 select!과 결합하면 하트비트나 폴링 반복문처럼 다른 채널과 함께 주기적인 작업을 실행할 수 있습니다.

use crossbeam_channel::{tick, select};
use std::time::Duration;

fn main() {
    let ticker = tick(Duration::from_millis(50));
    let mut count = 0;
    while count < 3 {
        select! {
            recv(ticker) -> _ => {
                count += 1;
                println!("tick {}", count);
            }
        }
    }
}

단계로 구성된 파이프라인

파이프라인 구축에서 Crossbeam은 뛰어난 성능을 발휘합니다. 첫 번째 단계가 생성하고, 두 번째 단계가 변환하며, 세 번째 단계가 소비합니다. 각 단계는 채널로 연결된 자체 스레드에서 실행되며, 수신기를 복제하면 어느 단계든 여러 작업자로 확장할 수 있습니다.

use crossbeam_channel::unbounded;
use std::thread;

fn main() {
    let (in_s, in_r) = unbounded();
    let (out_s, out_r) = unbounded();
    thread::spawn(move || {
        for n in in_r { out_s.send(n * n).unwrap(); }
    });
    for n in 1..=4 { in_s.send(n).unwrap(); }
    drop(in_s);
    for sq in out_r { println!("square: {}", sq); }
}

Crossbeam이 std보다 뛰어난 경우

다음과 같은 경우에는 crossbeam-channel을 사용하십시오.

  • 하나의 큐를 공유하는 여러 소비자(작업자 풀)가 필요한 경우
  • 시간 제한과 함께 여러 채널에서 select!를 사용해야 하는 경우
  • 선택 작업에 통합된 주기적 타이머가 tick을 통해 필요한 경우

간단한 생산자 하나와 소비자 하나로 구성된 파이프라면 표준 mpsc로 충분하며 별도의 의존성도 필요하지 않습니다.

삭제하여 채널 닫기

std와 마찬가지로 crossbeam 채널은 (수신자 측의 경우) 모든 송신자가 삭제되거나 (송신자 측의 경우) 모든 수신자가 삭제되면 닫힙니다. 마지막 송신자가 삭제되면 수신기 반복도 끝납니다. 작업자 루프가 깔끔하게 종료될 수 있도록 송신자를 항상 drop하거나 범위를 지정하십시오.

use crossbeam_channel::unbounded;
use std::thread;

fn main() {
    let (s, r) = unbounded();
    let h = thread::spawn(move || {
        let total: i32 = r.iter().sum();
        println!("total: {}", total);
    });
    for i in 1..=5 { s.send(i).unwrap(); }
    drop(s); // closes channel so the loop ends
    h.join().unwrap();
}

빠른 확인

crossbeam 채널에 대한 이해도를 확인해 보십시오.

복습

crossbeam 채널을 살펴보았습니다.

  • mpmc이므로 송신자와 수신자를 모두 복제할 수 있습니다.
  • unbounded()와 bounded(n)으로 버퍼링과 백프레셔를 제어합니다.
  • select!는 여러 채널을 기다리며, after로 시간 제한을 설정하고 tick으로 주기적 작업을 수행할 수 있습니다.
  • try_send/try_recv는 블로킹 없이 실행됩니다.
  • 작업자 풀과 복잡한 파이프라인에는 crossbeam을 사용하고, 간단한 파이프에는 std mpsc를 사용합니다.
무료로 시작

AI 튜터와 함께 Rust을(를) 배우세요 — 무료

브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.

코스
39
레슨
144

자주 묻는 질문

“Crossbeam 채널” 강의는 무료인가요?

네 — “Crossbeam 채널” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Learn Rust Coding 강의 전체를 잠금 해제할 수 있습니다. Learn Rust Coding 강의에는 총 4개의 강의가 포함되어 있습니다.

“Crossbeam 채널”에서 뭘 배우나요?

고급 채널 브라우저에서 직접 실행하는 실습 코드로 Learn Rust Coding을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Learn Rust Coding을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Learn Rust Coding은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“Crossbeam 채널” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Learn Rust Coding 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Learn Rust Coding 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. mpsc 채널
  2. Arc/Mutex로 상태 공유하기
  3. 범위가 지정된 스레드
  4. Crossbeam 채널
← Learn Rust Coding(으)로 돌아가기