并发
并发指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果
- 进程是一个程序的实例
- 线程是一个进程中执行的一个单一线性执行流程,一个进程包含多个线程,线程可以并发执行
main
是主线程,系统的入口
区别:
- 并发指一个系统能够同时处理多个任务,在单处理器上多个任务交替执行,看起来像同时执行
- 并行指一个系统能够同时处理多个任务,每个任务在不同核心执行,真正同时执行任务
交替执行,主线程结束新线程也会结束,本例新线程只执行5次
use std::thread;
use std::time::Duration;
fn main() {
thread::spawn(|| {
for i in 1..=10 {
println!("新线程{}", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..=5 {
println!("主线程{}", i);
thread::sleep(Duration::from_millis(1));
}
}
使用join handle
等待所有线程结束后再退出程序
use std::thread;
use std::time::Duration;
fn main() {
let handle = thread::spawn(|| {
for i in 1..=10 {
println!("新线程{}", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..=5 {
println!("主线程{}", i);
thread::sleep(Duration::from_millis(1));
}
handle.join().unwrap(); //阻塞主线程,直到新线程结束
}
使用其他线程的数据
use std::thread;
fn main() {
let v = vec![1, 2, 3];
let handle = thread::spawn(move || {
//整个程序是主线程,将v的所有权move到线程,使用其他线程的数据
println!("动态数组:{:?}", v); //动态数组:[1, 2, 3]
});
handle.join().unwrap();
}
Channel 管道
-
使用消息传递跨线程传递数据
-
Channel
:用通信共享内存,包含发送端、接收端 -
如果发送端、接收端任意一端被丢弃,那么
Channel
就关闭了
recv
:阻塞当前线程,有消息返回消息,发送端关闭返回RecvErr
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let val = String::from("hello");
tx.send(val).unwrap(); //发送消息
});
//recv阻止当前线程执行
let received = rx.recv().unwrap(); //接收消息,有消息返回消息,发送端关闭返回RecvErr
println!("接收:{}", received); //接收:hello
}
try_recv
:不阻塞当前线程,无消息返回Empty
错误,Channel
关闭返回Disconnected
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
fn main() {
// 创建一个通道,用于在不同线程之间传递消息
let (sender, receiver) = mpsc::channel();
// 启动一个新线程,发送消息到通道
thread::spawn(move || {
let messages = vec!["hello", "world", "from", "another", "thread"];
for msg in messages {
sender.send(msg.to_string()).unwrap();
thread::sleep(Duration::from_secs(1));
}
});
// 在主线程中接收通道中的消息
loop {
match receiver.try_recv() {
Ok(msg) => println!("收到消息: {}", msg),
Err(mpsc::TryRecvError::Empty) => {
println!("没有接收到消息, 等待...");
thread::sleep(Duration::from_secs(2));
}
Err(mpsc::TryRecvError::Disconnected) => {
println!("出错!, 关闭...");
break;
}
}
}
}
Rc<T>
引用计数类型,其数据可以有多个所有者
- 通过不可变引用,使程序不同部分共享只读数据
- 实现了
clone trait
,通过Rc::clone(&rc)
增加引用计数 - 共享不可变数据的所有权,避免大型数据结构的开销
- 单线程场景使用,性能开销低
#[derive(Debug)]
struct SharedData {
message: String,
}
fn main() {
use std::rc::Rc;
// 创建一个包含共享数据的 Rc 智能指针
let shared_data = Rc::new(SharedData {
message: String::from("Hello, Rc!"),
});
// 克隆 Rc 智能指针,增加引用计数
let shared_data1 = Rc::clone(&shared_data);
let shared_data2 = Rc::clone(&shared_data);
// 输出引用计数
println!("引用计数:{}", Rc::strong_count(<