Rust简明教程第九章-多线程&并发

并发

并发指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果

  • 进程是一个程序的实例
  • 线程是一个进程中执行的一个单一线性执行流程,一个进程包含多个线程,线程可以并发执行
  • 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(<
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cci497

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值