30.并发.rs
/*
安全高效的處理并發是 Rust 誕生的目的之一,主要解決的是服務器高負載承受能力。
并發(concurrent)的概念是只程序不同的部分獨立執行,這與并行(parallel)的概念容易混淆,并行強調的是"同時執行"。
Rust 中通過 std::thread::spawn 函數創建新線程.
*/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 函數的參數是一個無參函數thread::spawn(spawn_function); //隨著主線程的結束,spawn 線程也隨之結束了,并沒有完成所有打印。for i in 0..3 {println!("main thread print {}", i);thread::sleep(Duration::from_millis(1));}
}/*
可以使用閉包(closures)來傳遞函數作為參數
閉包是可以保存進變量或作為參數傳遞給其他函數的匿名函數。閉包相當于 C++ 中的 Lambda 表達式,格式如下:|參數1, 參數2, ...| -> 返回值類型 {// 函數體
}
*/
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));}
}//閉包練習使用
fn test_3() {let inc = |num: i32| -> i32 { num + 1 };println!("inc(5) = {}", inc(5));//閉包可以省略類型聲明使用 Rust 自動類型判斷機制: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 方法可以使子線程運行結束后再停止運行程序。handle.join().unwrap();
}//move 強制所有權遷移
fn test_5() {let s = "hello".to_string();// 在子線程中嘗試使用當前函數的資源,這一定是錯誤的!因為所有權機制禁止這種危險情況的產生,它將破壞所有權機制銷毀資源的一定性。// let handle = thread::spawn(|| {// println!("{}", s);// });// 我們可以使用閉包的 move 關鍵字來處理:let handle = thread::spawn(move || {//s.push_str("122222");println!("{}", s);});//轉移之后外面仍然可以用,s是String就不可用了//println!("{}", s);handle.join().unwrap();
}//Rust 中一個實現消息傳遞并發的主要工具是通道(channel),通道有兩部分組成,發送者(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();//這個就收是阻塞式調用,直到有數據才會解鎖//let received = rx.recv();//println!("only recv, no unwrap");let received = rx.recv().unwrap();println!("Got: {}", received);//如果發送是多次發送,那么接受也必須是多次接收let received = rx.recv().unwrap();println!("Got: {}", received);//如果對面沒有內容了,還進行接收那就返回空let 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 意為互斥對象,用來保護共享數據。Mutex 有下面幾個特征:
Mutex 會等待獲取鎖令牌(token),在等待過程中,會阻塞線程。直到鎖令牌得到。同時只有一個線程的 Mutex 對象獲取到鎖;
Mutex 通過 .lock() 或 .try_lock() 來嘗試得到鎖令牌,被保護的對象,必須通過這兩個方法返回的 RAII 守衛來調用,不能直接操作;
當 RAII 守衛作用域結束后,鎖會自動解開;
在多線程中,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 讀寫鎖
//同時允許多個讀,最多只能有一個寫;讀和寫不能同時存在;
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();
}
?
總結
- 上一篇: 29.rust类型转换.rs
- 下一篇: 31.错误处理.rs