Kanal mpsc
Mengirim antar-thread
Kanal mpsc adalah pelajaran Learn Rust Coding gratis di CoddyKit. Ini adalah pelajaran 1 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Learn Rust Coding, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Learn Rust Coding mencakup 4 pelajaran total.
Apa Itu Kanal?
Kanal adalah pipa satu arah untuk mengirim nilai dari satu thread ke thread lain. Pustaka standar Rust menyediakan std::sync::mpsc, dengan mpsc berarti banyak penghasil, satu penerima.
- Bagian Pengirim memasukkan nilai.
- Bagian Penerima mengambil nilai.
Kanal memungkinkan thread berkomunikasi dengan mengirim pesan, bukan berbagi memori secara langsung, sehingga banyak perlombaan data dapat dihindari.
Membuat Kanal
Panggil mpsc::channel() untuk mendapatkan tuple (Sender, Receiver). Di sini, kita mengirim satu nilai dari thread yang dibuat ke thread utama.
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
tx.send(42).unwrap();
});
let received = rx.recv().unwrap();
println!("Got: {}", received);
}send dan recv
tx.send(value) mengembalikan Result: operasi ini hanya gagal jika penerima telah dibuang. rx.recv() menunggu hingga suatu nilai tiba, dan mengembalikan Err saat semua pengirim sudah tidak ada.
sendmemindahkan kepemilikan nilai ke dalam kanal.recvmengambil kepemilikan dari sisi lainnya.
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let msg = String::from("hello from thread");
tx.send(msg).unwrap();
});
let text = rx.recv().unwrap();
println!("{}", text);
}Kepemilikan Berpindah Melalui Kanal
Karena send menerima nilai berdasarkan nilainya, Anda tidak dapat menggunakannya setelah mengirim. Aturan saat kompilasi ini menjamin tidak ada thread yang menyimpan referensi kedaluwarsa ke data yang kini dimiliki thread lain.
Di bawah ini, mencoba mencetak msg setelah send akan menjadi kesalahan kompilasi, jadi kita hanya menggunakannya sekali.
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let data = vec![1, 2, 3];
tx.send(data).unwrap();
// data is moved; cannot use it here
});
let v = rx.recv().unwrap();
println!("Sum: {}", v.iter().sum::<i32>());
}Melakukan Iterasi pada Penerima
Receiver mengimplementasikan IntoIterator. Perulangan pada objek ini menghasilkan setiap nilai hingga kanal ditutup (semua pengirim dibuang). Ini adalah cara idiomatis untuk menggunakan aliran pesan.
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
for i in 1..=3 {
tx.send(i).unwrap();
}
});
for received in rx {
println!("Received: {}", received);
}
}Banyak Penghasil dengan clone
mp dalam mpsc berarti Anda dapat memiliki banyak pengirim. Gandakan Sender dan berikan salinannya kepada setiap thread. Penerima mengumpulkan semuanya hingga semua salinan dibuang.
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
let tx2 = tx.clone();
thread::spawn(move || { tx.send("from A").unwrap(); });
thread::spawn(move || { tx2.send("from B").unwrap(); });
for msg in rx {
println!("{}", msg);
}
}Semantik Penutupan Kanal
Perulangan penerima berakhir secara otomatis saat semua pengirim dibuang. Jika bahkan satu Sender masih aktif, for msg in rx akan menunggu selamanya untuk pesan berikutnya. Selalu buang atau batasi cakupan pengirim dengan benar agar perulangan dapat selesai.
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
let handle = thread::spawn(move || {
for i in 0..3 {
tx.send(i * 10).unwrap();
}
// tx dropped here, closing the channel
});
handle.join().unwrap();
let total: i32 = rx.iter().sum();
println!("Total: {}", total);
}try_recv untuk Pembacaan Tanpa Menunggu
recv menunggu, tetapi try_recv segera mengembalikan Result. Nilainya adalah Ok(value) jika pesan siap, atau Err jika kanal kosong atau terputus. Ini berguna dalam perulangan peristiwa yang harus terus mengerjakan hal lain.
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
thread::sleep(Duration::from_millis(50));
tx.send("ready").unwrap();
});
loop {
match rx.try_recv() {
Ok(msg) => { println!("{}", msg); break; }
Err(_) => println!("waiting..."),
}
thread::sleep(Duration::from_millis(20));
}
}Mengirim Tipe Khusus
Tipe apa pun yang merupakan Send dapat dikirim melalui kanal, termasuk struct dan enum buatan Anda sendiri. Enum sangat cocok untuk memodelkan jenis pesan yang berbeda dalam protokol pekerja.
use std::sync::mpsc;
use std::thread;
enum Job {
Print(String),
Add(i32, i32),
}
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
tx.send(Job::Print(String::from("hi"))).unwrap();
tx.send(Job::Add(2, 3)).unwrap();
});
for job in rx {
match job {
Job::Print(s) => println!("print: {}", s),
Job::Add(a, b) => println!("add: {}", a + b),
}
}
}sync_channel dan Tekanan Balik
mpsc::sync_channel(n) membuat kanal terbatas dengan ukuran penyangga n. Saat penyangga penuh, send menunggu hingga ruang tersedia. Ini memberikan tekanan balik, sehingga penghasil yang cepat tidak membebani konsumen yang lambat.
sync_channel(0)adalah kanal pertemuan: send dan recv harus bertemu.
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::sync_channel(2);
thread::spawn(move || {
for i in 1..=4 {
tx.send(i).unwrap();
println!("sent {}", i);
}
});
for v in rx {
println!("got {}", v);
}
}Pola Pekerja Sederhana
Saluran sangat cocok untuk pola produsen/konsumen: satu utas menghasilkan item pekerjaan, utas lain mengonsumsi dan memprosesnya. Di sini, utas utama menghasilkan angka dan sebuah pekerja menguadratkan setiap angka lalu mengirimkan hasilnya melalui saluran kedua.
use std::sync::mpsc;
use std::thread;
fn main() {
let (job_tx, job_rx) = mpsc::channel();
let (res_tx, res_rx) = mpsc::channel();
thread::spawn(move || {
for n in job_rx {
res_tx.send(n * n).unwrap();
}
});
for n in 1..=4 {
job_tx.send(n).unwrap();
}
drop(job_tx);
for r in res_rx {
println!("square: {}", r);
}
}Pemeriksaan Singkat
Uji pemahaman Anda tentang saluran mpsc.
Rangkuman
Anda telah mempelajari inti saluran mpsc:
mpsc::channel()mengembalikan pasangan(Sender, Receiver).sendmemasukkan sebuah nilai;recvmenunggu untuk mengambilnya.- Melakukan iterasi pada penerima mengonsumsi pesan hingga semua pengirim dilepas.
- Gandakan
Senderuntuk membuat beberapa produsen. try_recvtidak menunggu;sync_channel(n)menambahkan tekanan balik berbatas.
Saluran memungkinkan utas berbagi data dengan aman melalui pemindahan kepemilikan, bukan berbagi memori.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Kanal mpsc” gratis?
Ya — teks lengkap “Kanal mpsc” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Learn Rust Coding, upgrade ke CoddyKit PRO. Kursus Learn Rust Coding mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Kanal mpsc”?
Mengirim antar-thread Kamu berlatih Learn Rust Coding dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Learn Rust Coding?
Tidak diperlukan pengalaman sebelumnya. Learn Rust Coding di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 1 dari 4.
Berapa lama pelajaran “Kanal mpsc” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Learn Rust Coding ini?
Ya. Setiap pelajaran Learn Rust Coding menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.