Rust:并发编程(concurrent programming)
得益于所有權(quán)系統(tǒng)以及類型系統(tǒng),Rust有著非常優(yōu)異的并發(fā)性能。
1. 線程的基本應(yīng)用
創(chuàng)建線程:
use std::thread; use std::time::Duration; fn main() {thread::spawn(|| {for i in 1..10 {println!("hi number {} from the spawned thread!", i);thread::sleep(Duration::from_millis(1));}});for i in 1..5 {println!("hi number {} from the main thread!", i);thread::sleep(Duration::from_millis(1));} } hi number 1 from the main thread! hi number 1 from the spawned thread! hi number 2 from the spawned thread! hi number 2 from the main thread! hi number 3 from the main thread! hi number 3 from the spawned thread! hi number 4 from the spawned thread! hi number 4 from the main thread! hi number 5 from the spawned thread!需要注意的是,當(dāng)主線程結(jié)束,不管thread::spawn創(chuàng)建的子線程是否執(zhí)行完畢,程序都會結(jié)束。所以子線程的print語句只執(zhí)行到了i=5。
使用Join()讓主線程等待子線程執(zhí)行完畢:
如果我們想讓子線程執(zhí)行完畢,可以將thread::spawn賦給變量,然后調(diào)用join。在rust中,thread::spawn返回的type是JoinHandle。
use std::thread; use std::time::Duration; fn main() {//thread::spawn創(chuàng)建線程后返回JoinHandle 類型給handlelet handle = thread::spawn(|| {for i in 1..10 {println!("hi number {} from the spawned thread!", i);thread::sleep(Duration::from_millis(1));}});for i in 1..5 {println!("hi number {} from the main thread!", i);thread::sleep(Duration::from_millis(1));}//調(diào)用join,讓主線程等待至子線程執(zhí)行完畢//unwrap的作用:請求返回結(jié)果,如果報錯就會panic并停止程序handle.join().unwrap(); } hi number 1 from the main thread! hi number 2 from the main thread! hi number 1 from the spawned thread! hi number 3 from the main thread! hi number 2 from the spawned thread! hi number 4 from the main thread! hi number 3 from the spawned thread! hi number 4 from the spawned thread! hi number 5 from the spawned thread! hi number 6 from the spawned thread! hi number 7 from the spawned thread! hi number 8 from the spawned thread! hi number 9 from the spawned thread!使用Move讓線程獲得變量所有權(quán)
在Rust里,當(dāng)閉包函數(shù)使用外界環(huán)境的變量時,編譯器會推斷閉包函數(shù)該采用借用,還是獲取變量所有權(quán)的方式。當(dāng)創(chuàng)建的子線程需要使用主線程的數(shù)據(jù)時,由于閉包函數(shù)運行子線程環(huán)境中而無法確定借用是否一直有效,所以需要使用move來使變量所有權(quán)移交至子線程的閉包函數(shù)。
use std::thread; fn main() {let v = vec![1, 2, 3];//使用move移交所有權(quán)至子線程let handle = thread::spawn(move|| {println!("Here's a vector: {:?}", v);});handle.join().unwrap(); }2. 線程通信機制:channel,transmitter與receiver
Rust book中將rust的線程通信的channel比作一條河,數(shù)據(jù)比作橡皮鴨。橡皮鴨從上游(transmitter)順流而下到下游(receiver)。Rust中實現(xiàn)線程通信的標(biāo)準(zhǔn)庫為mpsc,是multiple producer; single consumer的縮寫。意思是在rust線程通信機制中,可以有多個數(shù)據(jù)發(fā)送端,然后像河流匯聚到大海一般,最終由一個接受端接收。
use std::thread; use std::sync::mpsc; fn main() {//創(chuàng)建channel//mpsc::channel()返回一個tuple,包含transmitter:tx , receiver:rx//在很多領(lǐng)域tx,rx都被當(dāng)做是transmitter與receiver的縮寫//所以rust book的這個例子也以此來命名let (tx, rx) = mpsc::channel();thread::spawn(move || {let val = String::from("hi");//transmitter從子線程發(fā)送數(shù)據(jù)tx.send(val).unwrap();//需要注意的是,此時val的所有權(quán)也被移交給了數(shù)據(jù)的接收線程});//主線程接受子線程數(shù)據(jù)let received = rx.recv().unwrap();println!("Got: {}", received); } Got: hiSending Multiple Values and Seeing the Receiver Waiting:
為了直觀展現(xiàn)出兩個線程通過channel保持communicating,對上述代碼做出一點修改:使用for循環(huán)發(fā)送多條value,并且每次發(fā)送間隔1秒。同樣也以for循環(huán)在主線程中接收數(shù)據(jù),這時rx被當(dāng)作一個iterator。每當(dāng)接收到一條數(shù)據(jù),for循環(huán)就會執(zhí)行一次。直到數(shù)據(jù)發(fā)送完畢,channel關(guān)閉。
use std::thread; use std::sync::mpsc; 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"),];for val in vals {tx.send(val).unwrap();thread::sleep(Duration::from_secs(1));}});for received in rx {println!("Got: {}", received);} }應(yīng)該可以直觀的看到每條數(shù)據(jù)之間都間隔了1秒。
Got: hi Got: from Got: the Got: thread使用clone函數(shù)實現(xiàn)mpsc: multiple producer; single consumer
use std::thread; use std::sync::mpsc; use std::time::Duration; fn main() {let (tx, rx) = mpsc::channel();//使用clone函數(shù)clone一個transmitterlet tx1 = mpsc::Sender::clone(&tx);thread::spawn(move || {let vals = vec![String::from("hi"),String::from("from"),String::from("the"),String::from("thread"),];for val in vals {tx.send(val).unwrap();thread::sleep(Duration::from_secs(1));}});thread::spawn(move || {let vals = vec![String::from("more"),String::from("messages"),String::from("for"),String::from("you"),];for val in vals {tx1.send(val).unwrap();thread::sleep(Duration::from_secs(1));}});for received in rx {println!("Got: {}", received);} } Got: hi Got: more Got: from Got: messages Got: the Got: for Got: you Got: thread總結(jié)
以上是生活随笔為你收集整理的Rust:并发编程(concurrent programming)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据标注去哪接任务订单?靠谱的数据标注平
- 下一篇: remix共享本地文件夹