Canales Crossbeam
Canales avanzados
Canales Crossbeam es una lección gratuita de Learn Rust Coding en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Learn Rust Coding, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Learn Rust Coding incluye 4 lecciones en total.
Más allá de std mpsc
El canal estándar mpsc tiene un único consumidor: solo un receptor. El crate crossbeam-channel ofrece canales multi-productor y multi-consumidor (mpmc), con más funciones y, a menudo, un mejor rendimiento.
Aspectos destacados:
Receiverclonables, no solo emisores.- Una macro
select!potente para esperar en varios canales. - Canales acotados, no acotados y especiales, como los ticks.
Añadir la dependencia
Crossbeam es un crate externo, así que añádalo a Cargo.toml:
[dependencies]crossbeam-channel = "0.5"
Después, importe sus funciones. Como esto requiere Cargo y un crate externo, los fragmentos de aquí ilustran la API en lugar de ejecutarse de forma independiente.
// 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());
}unbounded y bounded
Crossbeam ofrece dos constructores principales:
unbounded()crece según sea necesario;sendnunca se bloquea.bounded(cap)tiene un búfer fijo;sendse bloquea cuando está lleno, lo que proporciona contrapresión.
Un canal bounded(0) es un canal de rendezvous en el que send y recv entregan los valores directamente.
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);
}
}Varios consumidores
La ventaja principal es que puede clonar el Receiver. Varios subprocesos de trabajo pueden extraer mensajes del mismo canal, y cada mensaje llega exactamente a uno de ellos. Esta es la base de un grupo de subprocesos con work stealing.
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(); }
}La macro select!
select! permite que un subproceso espere operaciones en varios canales y actúe sobre la primera que esté lista. Es como un match sobre eventos de canales, ideal para combinar entradas de varias fuentes.
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()),
}
}
}Tiempos de espera con select!
select! admite una rama default y una rama de temporizador recv(after(duration)), de modo que puede dejar de esperar tras un tiempo límite en lugar de bloquearse indefinidamente. Esto es esencial para los sistemas con capacidad de respuesta.
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 y try_recv
Al igual que la biblioteca estándar, crossbeam proporciona variantes no bloqueantes. try_send falla inmediatamente si un canal acotado está lleno; try_recv falla inmediatamente si no hay ningún mensaje listo. Ambos devuelven un error descriptivo que puede analizar con un match.
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 y trabajo periódico
La función tick(duration) devuelve un receptor que entrega un mensaje a intervalos fijos. Combínela con select! para ejecutar tareas periódicas junto con otros canales, como un latido o un bucle de sondeo.
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);
}
}
}
}Una canalización de etapas
Crossbeam destaca en la creación de canalizaciones: la etapa uno produce, la etapa dos transforma y la etapa tres consume. Cada etapa se ejecuta en su propio subproceso conectado mediante canales, y los receptores clonados permiten escalar cualquier etapa a varios trabajadores.
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); }
}Cuándo crossbeam supera a std
Use crossbeam-channel cuando necesite:
- Varios consumidores compartiendo una cola (grupos de trabajadores).
select!sobre muchos canales con tiempos de espera.- Temporizadores periódicos mediante
tickintegrados en la selección.
Para una tubería sencilla de un productor y un consumidor, el mpsc estándar es suficiente y no necesita ninguna dependencia.
Los canales se cierran al descartar sus valores
Al igual que en std, los canales de crossbeam se cierran cuando se descartan todos los emisores (desde el lado del receptor) o todos los receptores (desde el lado del emisor). La iteración sobre un receptor termina cuando se descarta el último emisor. Use siempre drop o limite el ámbito de los emisores para que los bucles de trabajo puedan terminar correctamente.
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();
}Comprobación rápida
Ponga a prueba su comprensión de los canales de crossbeam.
Resumen
Ha explorado los canales de crossbeam:
- Son mpmc: tanto los emisores como los receptores se pueden clonar.
unbounded()ybounded(n)controlan el almacenamiento en búfer y la contrapresión.select!espera en varios canales, con tiempos de espera medianteafterytickperiódico.try_send/try_recvno bloquean.- Use crossbeam para grupos de trabajadores y canalizaciones complejas; use std mpsc para tuberías sencillas.
Preguntas frecuentes
¿La lección «Canales Crossbeam» es gratis?
Sí — el texto completo de «Canales Crossbeam» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Learn Rust Coding, actualiza a CoddyKit PRO. El curso de Learn Rust Coding incluye 4 lecciones en total.
¿Qué aprenderé en «Canales Crossbeam»?
Canales avanzados Practicas Learn Rust Coding con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Learn Rust Coding?
No se requiere experiencia previa. Learn Rust Coding en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.
¿Cuánto tiempo toma la lección «Canales Crossbeam»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Learn Rust Coding?
Sí. Cada lección de Learn Rust Coding incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Canales mpsc
- Compartir estado con Arc/Mutex
- Hilos con ámbito
- Canales Crossbeam