40·并发编程进阶

线程 std::thread

线程 std::thread

学习目标

  1. 掌握线程创建和管理
  2. 理解 move 闭包
  3. 掌握线程通信

核心概念

创建线程

use std::thread;
use std::time::Duration;

fn main() {
    let handle = thread::spawn(|| {
        for i in 1..=5 {
            println!("子线程: {}", i);
            thread::sleep(Duration::from_millis(100));
        }
    });

    for i in 1..=3 {
        println!("主线程: {}", i);
        thread::sleep(Duration::from_millis(150));
    }

    handle.join().unwrap();  // 等待子线程完成
}

move 闭包

use std::thread;

fn main() {
    let data = vec![1, 2, 3];

    // 必须用 move 转移所有权
    let handle = thread::spawn(move || {
        println!("子线程收到: {:?}", data);
    });

    // println!("{:?}", data);  // ❌ 已移动
    handle.join().unwrap();
}

多线程

use std::thread;

fn main() {
    let mut handles = vec![];

    for i in 0..5 {
        let handle = thread::spawn(move || {
            println!("线程 {} 在工作", i);
            i * i
        });
        handles.push(handle);
    }

    let results: Vec<i32> = handles
        .into_iter()
        .map(|h| h.join().unwrap())
        .collect();

    println!("结果: {:?}", results);
}

线程数量

use std::thread;

fn main() {
    let num_threads = thread::available_parallelism()
        .map(|n| n.get())
        .unwrap_or(4);
    println!("可用线程数: {}", num_threads);
}

Builder 配置

use std::thread;

fn main() {
    let builder = thread::Builder::new()
        .name("worker-1".to_string())
        .stack_size(4 * 1024 * 1024);  // 4MB 栈

    let handle = builder.spawn(|| {
        println!("线程名: {:?}", thread::current().name());
    }).unwrap();

    handle.join().unwrap();
}

实践练习

练习 1:并行计算

use std::thread;

fn parallel_sum(data: &[i32], num_chunks: usize) -> i32 {
    let chunk_size = (data.len() + num_chunks - 1) / num_chunks;
    let chunks: Vec<Vec<i32>> = data.chunks(chunk_size)
        .map(|c| c.to_vec())
        .collect();

    let handles: Vec<_> = chunks.into_iter().map(|chunk| {
        thread::spawn(move || -> i32 {
            chunk.iter().sum()
        })
    }).collect();

    handles.into_iter()
        .map(|h| h.join().unwrap())
        .sum()
}

fn main() {
    let data: Vec<i32> = (1..=1000).collect();
    let result = parallel_sum(&data, 4);
    println!("总和: {}", result);
}

练习 2:生产者-消费者

use std::thread;
use std::sync::mpsc;

fn main() {
    let (tx, rx) = mpsc::channel();

    let producer = thread::spawn(move || {
        for i in 0..10 {
            tx.send(i).unwrap();
            thread::sleep(std::time::Duration::from_millis(100));
        }
    });

    let consumer = thread::spawn(move || {
        for received in rx {
            println!("收到: {}", received);
        }
    });

    producer.join().unwrap();
    consumer.join().unwrap();
}

常见错误

1. 忘记 join

let handle = thread::spawn(|| { /* ... */ });
// handle.join().unwrap();  // 必须 join,否则可能提前退出

2. 数据竞争

// ❌ 多个线程同时可变访问
// ✅ 用 Mutex 或 mpsc channel

小结

操作语法
创建线程thread::spawn(closure)
等待完成handle.join()
移动数据move || { }
休眠thread::sleep(duration)

练习编辑器

rust
Loading...