30.并发.rs
/*
安全高效的處理并發(fā)是 Rust 誕生的目的之一,主要解決的是服務(wù)器高負(fù)載承受能力。
并發(fā)(concurrent)的概念是只程序不同的部分獨(dú)立執(zhí)行,這與并行(parallel)的概念容易混淆,并行強(qiáng)調(diào)的是"同時(shí)執(zhí)行"。
Rust 中通過(guò) std::thread::spawn 函數(shù)創(chuàng)建新線程.
*/use std::sync::mpsc;
use std::thread;
use std::time::Duration;fn spawn_function() {for i in 0..5 {println!("spawned thread print {}", i);thread::sleep(Duration::from_millis(1));}
}fn test_1() {//std::thread::spawn 函數(shù)的參數(shù)是一個(gè)無(wú)參函數(shù)thread::spawn(spawn_function); //隨著主線程的結(jié)束,spawn 線程也隨之結(jié)束了,并沒(méi)有完成所有打印。for i in 0..3 {println!("main thread print {}", i);thread::sleep(Duration::from_millis(1));}
}/*
可以使用閉包(closures)來(lái)傳遞函數(shù)作為參數(shù)
閉包是可以保存進(jìn)變量或作為參數(shù)傳遞給其他函數(shù)的匿名函數(shù)。閉包相當(dāng)于 C++ 中的 Lambda 表達(dá)式,格式如下:|參數(shù)1, 參數(shù)2, ...| -> 返回值類(lèi)型 {// 函數(shù)體
}
*/
fn test_2() {thread::spawn(|| {for i in 0..5 {println!("spawned thread print {}", i);thread::sleep(Duration::from_millis(1));}});for i in 0..3 {println!("main thread print {}", i);thread::sleep(Duration::from_millis(1));}
}//閉包練習(xí)使用
fn test_3() {let inc = |num: i32| -> i32 { num + 1 };println!("inc(5) = {}", inc(5));//閉包可以省略類(lèi)型聲明使用 Rust 自動(dòng)類(lèi)型判斷機(jī)制:let inc = |num| num + 1;println!("inc(5) = {}", inc(5));
}//join 方法.
fn test_4() {let handle = thread::spawn(|| {for i in 0..5 {println!("spawned thread print {}", i);thread::sleep(Duration::from_millis(1));}});for i in 0..3 {println!("main thread print {}", i);thread::sleep(Duration::from_millis(1));}//join 方法可以使子線程運(yùn)行結(jié)束后再停止運(yùn)行程序。handle.join().unwrap();
}//move 強(qiáng)制所有權(quán)遷移
fn test_5() {let s = "hello".to_string();// 在子線程中嘗試使用當(dāng)前函數(shù)的資源,這一定是錯(cuò)誤的!因?yàn)樗袡?quán)機(jī)制禁止這種危險(xiǎn)情況的產(chǎn)生,它將破壞所有權(quán)機(jī)制銷(xiāo)毀資源的一定性。// let handle = thread::spawn(|| {// println!("{}", s);// });// 我們可以使用閉包的 move 關(guān)鍵字來(lái)處理:let handle = thread::spawn(move || {//s.push_str("122222");println!("{}", s);});//轉(zhuǎn)移之后外面仍然可以用,s是String就不可用了//println!("{}", s);handle.join().unwrap();
}//Rust 中一個(gè)實(shí)現(xiàn)消息傳遞并發(fā)的主要工具是通道(channel),通道有兩部分組成,發(fā)送者(transmitter)和接收者(receiver)。
//std::sync::mpsc 包含了消息傳遞的方法:
fn test_6() {let (tx, rx) = mpsc::channel();let handle = thread::spawn(move || {thread::sleep(Duration::from_millis(1000));let hello = String::from("hello");let world = String::from("world");tx.send(hello).unwrap();tx.send(world).unwrap();});//handle.join().unwrap();//這個(gè)就收是阻塞式調(diào)用,直到有數(shù)據(jù)才會(huì)解鎖//let received = rx.recv();//println!("only recv, no unwrap");let received = rx.recv().unwrap();println!("Got: {}", received);//如果發(fā)送是多次發(fā)送,那么接受也必須是多次接收l(shuí)et received = rx.recv().unwrap();println!("Got: {}", received);//如果對(duì)面沒(méi)有內(nèi)容了,還進(jìn)行接收那就返回空l(shuí)et received = rx.recv();match received {Ok(str) => println!("Got: {}", str),Err(e) => println!("got nothing")}//println!("Got: {}", received);
}/*
https://rustcc.gitbooks.io/rustprimer/content/rcarc/mutex.html
Mutex 意為互斥對(duì)象,用來(lái)保護(hù)共享數(shù)據(jù)。Mutex 有下面幾個(gè)特征:
Mutex 會(huì)等待獲取鎖令牌(token),在等待過(guò)程中,會(huì)阻塞線程。直到鎖令牌得到。同時(shí)只有一個(gè)線程的 Mutex 對(duì)象獲取到鎖;
Mutex 通過(guò) .lock() 或 .try_lock() 來(lái)嘗試得到鎖令牌,被保護(hù)的對(duì)象,必須通過(guò)這兩個(gè)方法返回的 RAII 守衛(wèi)來(lái)調(diào)用,不能直接操作;
當(dāng) RAII 守衛(wèi)作用域結(jié)束后,鎖會(huì)自動(dòng)解開(kāi);
在多線程中,Mutex 一般和 Arc 配合使用。*/
use std::{sync::RwLock, thread};
use std::{sync::{mpsc::channel, Arc, Mutex},time::Duration,
};
const N: usize = 20;fn test_7() {println!("-----------------------test7-----------------------");let mutex = Arc::new(Mutex::new(0));for _ in 0..3 {let mutex2 = mutex.clone();thread::spawn(move || loop {let mut data = mutex2.lock().unwrap();*data += 1;if *data > N {break;}let tid = thread::current().id();println!("{:?}--{}", tid, data);});}thread::sleep(Duration::from_secs(1));
}fn test_8() {println!("-----------------------test8-----------------------");let mutex = Arc::new(Mutex::new(0));let (tx, rx) = channel();for _ in 0..3 {let (mutex2, tx) = (mutex.clone(), tx.clone());thread::spawn(move || loop {let mut data = mutex2.lock().unwrap();*data += 1;let tid = thread::current().id();tx.send((tid, *data)).unwrap();if *data >= N {break;}});}for _ in 0..N {let (tid, data) = rx.recv().unwrap();println!("{:?}--{}", tid, data);}
}//RwLock 讀寫(xiě)鎖
//同時(shí)允許多個(gè)讀,最多只能有一個(gè)寫(xiě);讀和寫(xiě)不能同時(shí)存在;
fn test_9() {println!("-----------------------test9-----------------------");let lock = RwLock::new(5);// many reader locks can be held at once{let r1 = lock.read().unwrap();let r2 = lock.read().unwrap();assert_eq!(*r1, 5);assert_eq!(*r2, 5);}// only one write lock may be held, however{let mut w = lock.write().unwrap();*w += 1;assert_eq!(*w, 6);}
}fn main() {test_1();test_2();test_3();test_4();test_5();test_6();test_7();test_8();test_9();
}
?
總結(jié)
- 上一篇: 29.rust类型转换.rs
- 下一篇: 31.错误处理.rs