Skip to content

Ch 29: std::thread - 线程基础

std::thread模块提供了Rust中的多线程编程支持。Rust的线程模型是1:1的,即每个语言级线程对应一个操作系统线程。

使用thread::spawn创建新线程:

use std::thread;
fn main() {
let handle = thread::spawn(|| {
println!("子线程执行中...");
42
});
println!("主线程继续执行");
// 等待子线程完成并获取结果
let result = handle.join().unwrap();
println!("子线程返回: {}", result);
}

闭包中的move关键字用于转移所有权:

use std::thread;
fn main() {
let data = vec![1, 2, 3];
// move转移data的所有权到子线程
let handle = thread::spawn(move || {
println!("子线程中的数据: {:?}", data);
// data在这里被使用后drop
});
// 主线程无法再使用data
// println!("{:?}", data); // 编译错误!
handle.join().unwrap();
}
use std::thread;
use std::time::Duration;
fn main() {
println!("开始...");
thread::sleep(Duration::from_secs(1));
println!("1秒后...");
thread::sleep(Duration::from_millis(500));
println!("再过0.5秒...");
// 支持纳秒精度
thread::sleep(Duration::from_nanos(1_000_000));
println!("1毫秒后...");
}

方法签名:

pub fn sleep(dur: Duration)

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());
println!("线程ID: {:?}", thread::current().id());
}).unwrap();
handle.join().unwrap();
}

Builder方法签名:

impl Builder {
pub fn new() -> Builder
pub fn name(self, name: String) -> Builder
pub fn stack_size(self, size: usize) -> Builder
pub fn spawn<F, T>(self, f: F) -> Result<JoinHandle<T>>
where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
}

spawn返回JoinHandle,用于等待线程结束:

use std::thread;
fn main() {
let handle = thread::spawn(|| {
"Hello from thread"
});
// join返回Result
match handle.join() {
Ok(result) => println!("线程返回: {}", result),
Err(e) => println!("线程panic: {:?}", e),
}
}

7. thread::current - 获取当前线程信息

Section titled “7. thread::current - 获取当前线程信息”
use std::thread;
fn main() {
let handle = thread::spawn(|| {
let current = thread::current();
println!("线程ID: {:?}", current.id());
println!("线程名: {:?}", current.name());
// 检查是否是主线程
println!("是主线程: {}", current.is_main());
});
println!("主线程ID: {:?}", thread::current().id());
println!("是主线程: {}", thread::current().is_main());
handle.join().unwrap();
}

scope确保所有线程在函数返回前完成:

use std::thread;
fn main() {
let data = vec![1, 2, 3, 4, 5];
// 所有子线程必须在scope返回前完成
thread::scope(|scope| {
for i in &data {
scope.spawn(|| {
println!("处理: {}", i);
});
}
});
println!("所有线程已完成,data仍可访问: {:?}", data);
}

使用thread_local!创建线程局部变量:

use std::cell::RefCell;
use std::thread;
thread_local! {
static THREAD_DATA: RefCell<String> = RefCell::new("初始值".to_string());
}
fn main() {
THREAD_DATA.with(|data| {
println!("主线程: {}", data.borrow());
});
let handle = thread::spawn(|| {
THREAD_DATA.with(|data| {
data.borrow_mut().push_str(" - 被线程修改");
println!("子线程: {}", data.borrow());
});
});
handle.join().unwrap();
// 主线程的值不受影响
THREAD_DATA.with(|data| {
println!("主线程(不变): {}", data.borrow());
});
}
use std::thread;
use std::time::Duration;
fn main() {
let handle = thread::spawn(|| {
println!("线程开始park");
thread::park();
println!("线程恢复执行");
});
println!("主线程sleep 1秒");
thread::sleep(Duration::from_secs(1));
println!(" unpark 子线程");
handle.thread().unpark();
handle.join().unwrap();
}
  1. panic处理:panic在单个线程中不会导致整个程序崩溃
  2. 资源清理:JoinHandle被drop时如果线程未结束,会自动detach成为守护线程
  3. 栈大小:默认栈大小约2MB,可通过Builder调整
  4. 线程数量:受限于系统线程数和资源
  5. LocalKey:使用with方法访问,必须提供初始值

std::thread核心API:

  • thread::spawn() - 创建线程
  • move闭包 - 转移所有权
  • thread::sleep() - 线程睡眠
  • Builder - 自定义线程属性
  • JoinHandle - 管理线程生命周期
  • thread::current() - 获取当前线程信息
  • scope() - 安全的作用域线程
  • LocalKey - 线程局部存储

Rust的线程安全通过所有权和类型系统保证,是构建并发程序的基础。