线程
线程
Rust 标准库支持线程、同步与并发。
语言和标准库本身提供基础能力,更多高级并发能力由生态 crate 提供,
本文不展开。
下表给出 .NET 与 Rust 在线程相关类型/方法上的近似映射:
| .NET | Rust |
|---|---|
Thread | std::thread::thread |
Thread.Start | std::thread::spawn |
Thread.Join | std::thread::JoinHandle |
Thread.Sleep | std::thread::sleep |
ThreadPool | - |
Mutex | std::sync::Mutex |
Semaphore | - |
Monitor | std::sync::Mutex |
ReaderWriterLock | std::sync::RwLock |
AutoResetEvent | std::sync::Condvar |
ManualResetEvent | std::sync::Condvar |
Barrier | std::sync::Barrier |
CountdownEvent | std::sync::Barrier |
Interlocked | std::sync::atomic |
Volatile | std::sync::atomic |
ThreadLocal | std::thread_local |
在 C#/.NET 中,创建线程并等待结束的写法如下:
using System;
using System.Threading;
var thread = new Thread(() => Console.WriteLine("Hello from a thread!"));
thread.Start();
thread.Join(); // wait for thread to finishRust 等价写法:
use std::thread;
fn main() {
let thread = thread::spawn(|| println!("Hello from a thread!"));
thread.join().unwrap(); // wait for thread to finish
}在 .NET 中,“创建线程对象”与“启动线程”是两个动作;Rust 里 thread::spawn
会同时完成创建与启动。
.NET 线程支持通过参数传值:
#nullable enable
using System;
using System.Text;
using System.Threading;
var t = new Thread(obj =>
{
var data = (StringBuilder)obj!;
data.Append(" World!");
});
var data = new StringBuilder("Hello");
t.Start(data);
t.Join();
Console.WriteLine($"Phrase: {data}");更现代/简洁的 C# 常用闭包:
using System;
using System.Text;
using System.Threading;
var data = new StringBuilder("Hello");
var t = new Thread(obj => data.Append(" World!"));
t.Start();
t.Join();
Console.WriteLine($"Phrase: {data}");Rust 没有“线程启动时直接传参”的 thread::spawn 变体,通常通过闭包捕获数据:
use std::thread;
fn main() {
let data = String::from("Hello");
let handle = thread::spawn(move || {
let mut data = data;
data.push_str(" World!");
data
});
println!("Phrase: {}", handle.join().unwrap());
}要点:
- 这里必须使用
move,把data的所有权移动到线程闭包中。移动后,main里的原变量不能再直接使用;如需复用,需要复制或克隆。 - Rust 线程与 C#
Task类似,也可以返回值,join可拿到该返回值。 - C# 也能用闭包传数据,但通常不需要显式处理所有权;对象生命周期由 GC 管理。