Rust thread

Rust中,线程是实现并发编程的核心工具,基于操作系统原生线程(1:1)模型,每个线程由操作系统直接调用

线程创建

使用std:🧵:spawn创建线程,接受闭包(匿名函数)作为线程入口

use std::thread;

fn main() {

    let handle = thread::spawn(|| {println!("new thread running");});
    handle.join().unwrap(); // 等待线程运行完成
    println!("主线程结束");
}

所有权与move

匿名函数默认捕获变量的引用,使用move强制转移所有权

let data = vec![1, 2, 3];
let handle = thread::spawn(move || {
    println!("子线程数据: {:?}", data); // data 所有权转移至闭包
});
// 此处无法再访问 data

错误处理

子线程panic不会传播到主线程,需通过join捕获

let handle = thread::spawn(|| {
    panic!("子线程崩溃");
});

if let Err(e) = handle.join() {
    println!("子线程错误: {:?}", e);
}

线程同步

  1. channel
use std::sync::mpsc;

let (sender, receiver) = mpsc::channel();

thread::spawn(move || {
    sender.send("message").unwrap();
});

println!("receive {}", receiver.recv().unwrap());

多个sender时需要clone(只克隆指针,增加引用计数,指向同一个对象)

use std::sync::mpsc;
use std::sync::Arc;
use std::thread;
use std::time::Duration;

struct Queue {
    length: u32,
    first_half: Vec<u32>,
    second_half: Vec<u32>,
}

impl Queue {
    fn new() -> Self {
        Queue {
            length: 10,
            first_half: vec![1, 2, 3, 4, 5],
            second_half: vec![6, 7, 8, 9, 10],
        }
    }
}

fn send_tx(q: Queue, tx: mpsc::Sender<u32>) -> () {
    let qc = Arc::new(q);
    let qc1 = Arc::clone(&qc);
    let qc2 = Arc::clone(&qc);
    let tx1 = tx.clone();

    thread::spawn(move || {
        for val in &qc1.first_half {
            println!("sending {:?}", val);
            tx1.send(*val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });

    thread::spawn(move || {
        for val in &qc2.second_half {
            println!("sending {:?}", val);
            tx.send(*val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });
}

fn main() {
    let (tx, rx) = mpsc::channel();
    let queue = Queue::new();
    let queue_length = queue.length;

    send_tx(queue, tx);

    let mut total_received: u32 = 0;
    for received in rx {
        println!("Got: {}", received);
        total_received += 1;
    }

    println!("total numbers received: {}", total_received);
    assert_eq!(total_received, queue_length)
}

Arc(原子引用计数)和 Mutex互斥锁

use std::sync::{Arc, Mutex};

let counter = Arc::new(Mutex::new(0));
let mut handlers = vec![];
for _ in 0..10 {
    let counter = Arc::clone(&counter); // 复制引用,只增加引用计数
    let handle = therad::spawn(move || {
        let mut num = counter.lock().unwrap();
        *num += 1;
    });
    handlers.push(handle);
}
for handle in handles {
    handle.join().unwrap();
}

println!("结果: {}", *counter.lock().unwrap());


线程安全与Trait

  1. Send trait : 允许类型的所有权在线程间转移,绝大多数类型自动实现,如i32、String
  2. Sync trait: 允许类型的不可变引用跨线程共享, 如Mutex
// Arc<Mutex<T>> 自动实现 Sync
let data: Arc<Mutex<i32>> = Arc::new(Mutex::new(0));
posted @ 2025-05-02 19:19  店里最会撒谎白玉汤  阅读(19)  评论(0)    收藏  举报