- 并发(Concurrent):程序的不同部分相互独立执行
- 并行(Parallel):程序不同部分同时执行
1 线程
1.1 基本使用
use std::thread;
use std::time::Duration;
fn main() {
let 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));
}
handle.join().unwrap();
}
thread::spawn()
在创建线程失败时会panic
,可以用std::thread::Builder::spawn()
来创建线程,失败时不会panic
thread::sleep()
、thread::sleep_ms()
、thread::yield_now()
thread::current()
、thread::park/unpark()
(暂停/恢复)1.2 对闭包使用
move
use std::thread;
fn main() {
let v = vec![1, 2, 3];
// 编译通不过:闭包的生存周期可能超过本函数,但是却借用了属于本函数的变量 v
// let handle = thread::spawn(|| {
// 通过关键字 move,指示将借用的变量的所有权转移到闭包中,闭包外面变量 v 已经失效,不得再使用
let handle = thread::spawn(move || {
println!("Here's a vector: {:?}", v);
});
//drop(v);// 即使没有这一句也编译通不过: 这一句只是说明,可能 v 已经失效,但是执行闭包的线程仍然借用着 v,这是不允许的
handle.join().unwrap();
}
2 通道
2.1 基本使用
use std::thread;
use std::sync::mpsc;
pub 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);
}
mpsc
表示多个生产者、单个消费者- 接收方法:
recv
、try_recv
、recv_timeout
、recv_deadline
、iter
、try_iter
- 发送端退出后,接收方将返回错误:但通道是缓冲的,发送端退出前发送的所有消息,接收方都可以接收
- 不存在接收方时,发送将失败;存在接收方时,发送一定成功:系统会缓存发送的内容,不限制缓存数量
- 被发送内容的所有权将转移到发送方法中!!!
- 异步通道:
mpsc::channel()
,缓存数量无上限 - 同步通道:
mpsc::sync_channel()
,必须指定一个缓存数量上限,通道满时发送方发送操作将阻塞; -
2.2 使用多个发送端
调用发送方的
clone
方法可以克隆出一个新的发送端,多个发送端可以并发工作
pub fn main2() {
let (tx, rx) = mpsc::channel();
let tx1 = mpsc::Sender::clone(&tx);
// 这样写也是正确的
// let tx1 = tx.clone();
thread::spawn(move || {
let vals = vec![
String::from("hi"),
String::from("from"),
String::from("the"),
String::from("thread"),
];
for val in vals {
tx1.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 {
tx.send(val).unwrap();
thread::sleep(Duration::from_secs(1));
}
});
for received in rx {
println!("Got: {}", received);
}
}
3 共享状态
3.1 Mutex<T>
use std::sync::Mutex;
fn main() {
let m = Mutex::new(5);
{
let mut num = m.lock().unwrap();
*num = 6;
}
println!("m = {:?}", m);
}
- 创建:
Mutex::new()
,这是一个泛型关联方法,可封装任意类型 - 获取封装的资源
use std::sync::{Mutex, Arc};
use std::thread;
fn main() {
let counter = Arc::new(Mutex::new(0));// 用 Arc<T> 封装 Mutex<T>
let mut handles = vec![];
for _ in 0..10 {
let counter = Arc::clone(&counter);// 克隆
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();// Mutex<T> 实现了内部可变性,通过不可变的 counter 可以改变内部封装的值
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", *counter.lock().unwrap());
}