Rust使用Channel實(shí)現(xiàn)跨線(xiàn)程傳遞數(shù)據(jù)
1. 概述
消息傳遞是一種很流行且能保證安全并發(fā)的技術(shù),在這種機(jī)制里線(xiàn)程(或Actor)通過(guò)彼此發(fā)送消息(數(shù)據(jù))來(lái)進(jìn)行通信。Go語(yǔ)言中有一句名言:“不要用共享內(nèi)存來(lái)通信,要用通信來(lái)共享內(nèi)存”,Go語(yǔ)言這種并發(fā)機(jī)制就體現(xiàn)了這個(gè)思想。
Rust也提供了一種基于消息傳遞的并發(fā)方式,在rust里使用標(biāo)準(zhǔn)庫(kù)提供的Channel來(lái)實(shí)現(xiàn)。Channel包含發(fā)送端和接收端,我們可以通過(guò)調(diào)用發(fā)送端的方法來(lái)發(fā)送數(shù)據(jù),接收端會(huì)檢查和接收到達(dá)的數(shù)據(jù)。如果發(fā)送端和接收端的任意一端被丟棄了,那么Channel就關(guān)閉了。
2. 使用Channel
2.1 在不同線(xiàn)程之間創(chuàng)建和接收數(shù)據(jù)
使用mpsc::channel函數(shù)來(lái)創(chuàng)建Channel,mpsc表示multiple producer, singer consumer(多個(gè)生產(chǎn)者、一個(gè)消費(fèi)者),即有多個(gè)發(fā)送端,但只有一個(gè)接收端。調(diào)用該函數(shù)將返回一個(gè)元組,元組里的元素分別是發(fā)送端、接收端。
如下示例代碼:
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let val = String::from("hi");
tx.send(val).unwrap();
});
let received = rx.recv().unwrap();
println!("Got: {}", received);
}
消費(fèi)者的recv方法一直會(huì)阻塞當(dāng)前線(xiàn)程,直到接收到消息為止。
2.2 發(fā)送端的send方法
該方法的參數(shù)為想要發(fā)送的數(shù)據(jù),返回值為Result<T, E>,如果有問(wèn)題(例如接收端已經(jīng)被丟棄),將返回一個(gè)錯(cuò)誤。
2.3 接收端的方法
recv方法阻止當(dāng)前線(xiàn)程執(zhí)行,直到Channel中有值被送來(lái)。一旦收到值,就會(huì)返回Result<T>,所有這個(gè)管道的所有發(fā)送端都關(guān)閉了,就會(huì)收到一個(gè)錯(cuò)誤。
try_recv方法不會(huì)阻塞當(dāng)前的線(xiàn)程,如果有數(shù)據(jù)到達(dá),返回OK,里面包含著數(shù)據(jù),否則返回錯(cuò)誤。我們通常會(huì)使用循環(huán)來(lái)檢查try_recv的結(jié)果,如果消息還沒(méi)有來(lái),我們也可以執(zhí)行其他的操作。
2.4 channel和所有權(quán)轉(zhuǎn)移
所有權(quán)先消息傳遞中非常重要,能幫你補(bǔ)全編寫(xiě)安全、并發(fā)的代碼。
我們先看以下的示例代碼:
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let val = String::from("hi");
tx.send(val).unwrap();
// 下面一行代碼將會(huì)報(bào)錯(cuò),因?yàn)樗袡?quán)已經(jīng)被轉(zhuǎn)移
println("val is {}", val);
});
let received = rx.recv().unwrap();
println!("Got: {}", received);
}
在上面的示例代碼中,借用了已移動(dòng)的值,因此會(huì)發(fā)生編譯錯(cuò)誤。所以所有權(quán)機(jī)制會(huì)幫助我們編寫(xiě)編寫(xiě)安全、并發(fā)的代碼。
2.5 發(fā)送多個(gè)值
我們通過(guò)發(fā)送多個(gè)值,就可以看到接收者在等待的過(guò)程。
如下示例代碼:
use std::sync::mpsc;
use std::{thread, vec};
use std::time::Duration;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let vals = vec![
String::from("hi"),
String::from("from"),
String::from("the"),
String::from("thread"),
];
// 循環(huán)分別發(fā)送四個(gè)字符串
for val in vals {
tx.send(val).unwrap();
thread::sleep(Duration::from_millis(1000));
}
});
// 我們把接收端當(dāng)作迭代器來(lái)使用,這樣就不需要顯式調(diào)用recv方法
for received in rx {
println!("Got: {}", received);
}
}
運(yùn)行以上的代碼,我們將看到接收端在等待消息的過(guò)程。
2.6 通過(guò)克隆創(chuàng)建多個(gè)發(fā)送者
通過(guò)調(diào)用mpsc::Sender::clone函數(shù)可以克隆發(fā)送者。
如下示例代碼:
use std::sync::mpsc;
use std::{thread, vec};
use std::time::Duration;
fn main() {
let (tx, rx) = mpsc::channel();
let tx1 = mpsc::Sender::clone(&tx);
thread::spawn(move || {
let vals = vec![
String::from("1: hi"),
String::from("1: from"),
String::from("1: the"),
String::from("1: thread"),
];
// 循環(huán)分別發(fā)送四個(gè)字符串
for val in vals {
tx1.send(val).unwrap();
thread::sleep(Duration::from_millis(200));
}
});
thread::spawn(move || {
let vals = vec![
String::from("hi"),
String::from("from"),
String::from("the"),
String::from("thread"),
];
// 循環(huán)分別發(fā)送四個(gè)字符串
for val in vals {
tx.send(val).unwrap();
thread::sleep(Duration::from_millis(200));
}
});
// 我們把接收端當(dāng)作迭代器來(lái)使用,這樣就不需要顯式調(diào)用recv方法
for received in rx {
println!("Got: {}", received);
}
}
在以上的示例代碼中,我們通過(guò)兩個(gè)子線(xiàn)程由兩個(gè)發(fā)送者來(lái)發(fā)數(shù)據(jù)。并在主線(xiàn)程中使用接收者接收數(shù)據(jù),可以通過(guò)程序運(yùn)行結(jié)果看到由兩個(gè)發(fā)送者發(fā)送的數(shù)據(jù)被交替輸出。
到此這篇關(guān)于Rust使用Channel實(shí)現(xiàn)跨線(xiàn)程傳遞數(shù)據(jù)的文章就介紹到這了,更多相關(guān)Rust Channel跨線(xiàn)程傳遞數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Rust使用Trait對(duì)象實(shí)現(xiàn)多態(tài)的詳細(xì)步驟
本文詳細(xì)介紹了在Rust中使用Trait對(duì)象實(shí)現(xiàn)運(yùn)行時(shí)多態(tài)的方法,通過(guò)一個(gè)圖形渲染系統(tǒng)的案例展示了如何統(tǒng)一管理不同類(lèi)型的圖形對(duì)象,文章涵蓋了Trait對(duì)象的核心概念、語(yǔ)法、性能考量以及在實(shí)際項(xiàng)目中的應(yīng)用場(chǎng)景,感興趣的朋友跟隨小編一起看看吧2025-11-11
Rust中print和println的區(qū)別實(shí)例解析
Rust中print!和println!宏用于輸出,區(qū)別在于println!自動(dòng)換行,print!不換行,前者適用于同一行內(nèi)組合輸出,后者用于獨(dú)立日志或需換行場(chǎng)景,均支持格式化參數(shù),如{},本文給大家介紹Rust中print和println的區(qū)別,感興趣的朋友一起看看吧2025-06-06
Rust語(yǔ)言數(shù)據(jù)類(lèi)型的具體使用
在Rust中,每個(gè)值都有一個(gè)明確的數(shù)據(jù)類(lèi)型,本文主要介紹了Rust語(yǔ)言數(shù)據(jù)類(lèi)型的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下2024-04-04
如何使用rust實(shí)現(xiàn)簡(jiǎn)單的單鏈表
實(shí)現(xiàn)單鏈表在別的語(yǔ)言里面可能是一件簡(jiǎn)單的事情,單對(duì)于Rust來(lái)說(shuō),絕對(duì)不簡(jiǎn)單,下面這篇文章主要給大家介紹了關(guān)于如何使用rust實(shí)現(xiàn)簡(jiǎn)單的單鏈表的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-03-03

