并发基础
概念名称: 并发是多个任务交替执行,并行是多个任务同时执行。
最简示例
rust
▶ Runuse std::thread;
fn main() {
let handle = thread::spawn(|| {
println!("子线程运行");
});
handle.join().unwrap();
}并发 vs 并行
┌─────────────────────────────────────────────────────┐
│ 并发 vs 并行 │
├─────────────────────────────────────────────────────┤
│ │
│ 并发 (Concurrency) │
│ ┌───────────────────────────────────────────┐ │
│ │ 多个任务交替执行 │ │
│ │ ▓▓░░░░░░ 任务 A │ │
│ │ ░░▓▓░░░░ 任务 B │ │
│ │ ░░░░▓▓░░ 任务 C │ │
│ └───────────────────────────────────────────┘ │
│ 单个 CPU 核心,时间片轮转 │
│ │
│ 并行 (Parallelism) │
│ ┌───────────────────────────────────────────┐ │
│ │ 多个任务同时执行 │ │
│ │ ▓▓▓▓▓▓▓▓ 任务 A (核心 1) │ │
│ │ ▓▓▓▓▓▓▓▓ 任务 B (核心 2) │ │
│ │ ▓▓▓▓▓▓▓▓ 任务 C (核心 3) │ │
│ └───────────────────────────────────────────┘ │
│ 多个 CPU 核心,真正同时 │
│ │
└─────────────────────────────────────────────────────┘为什么用它?
rust
▶ Run// 没有并发:任务顺序执行,慢
for i in 0..3 {
process_task(i); // 每个任务等前一个完成
}
// 有并发:任务同时运行,快
let handles: Vec<_> = (0..3).map(|i| {
thread::spawn(move || process_task(i))
}).collect();
for h in handles {
h.join().unwrap();
}Rust 并发优势
Rust 在编译时防止数据竞争!
数据竞争条件:
1. 两个或以上线程同时访问同一数据
2. 至少有一个线程在写入
3. 没有同步机制
Rust 的所有权系统 + 类型系统 = 编译时消除数据竞争创建线程
rust
▶ Runuse std::thread;
use std::time::Duration;
fn main() {
// 创建线程
let handle = thread::spawn(|| {
for i in 1..10 {
println!("子线程:{}", i);
thread::sleep(Duration::from_millis(10));
}
});
// 主线程工作
for i in 1..5 {
println!("主线程:{}", i);
thread::sleep(Duration::from_millis(10));
}
// 等待子线程完成
handle.join().unwrap();
println!("完成!");
}关键代码说明:
| 代码 | 含义 | 为什么这样写 |
|---|---|---|
| `thread::spawn( | {...})` | |
handle.join() | 等待线程完成 | 阻塞直到线程结束 |
move 闭包 | 转移所有权到线程 | 线程需要拥有捕获的数据 |
thread::sleep() | 暂停线程 | 模拟耗时操作 |
| ┌─────────────────────────────────────────────────────┐ | ||
| │ 并发 vs 并行 │ | ||
| ├─────────────────────────────────────────────────────┤ | ||
| │ │ | ||
| │ 并发 (Concurrency) │ | ||
| │ ┌───────────────────────────────────────────┐ │ | ||
| │ │ 多个任务交替执行 │ │ | ||
| │ │ ▓▓░░░░░░ 任务 A │ │ | ||
| │ │ ░░▓▓░░░░ 任务 B │ │ | ||
| │ │ ░░░░▓▓░░ 任务 C │ │ | ||
| │ └───────────────────────────────────────────┘ │ | ||
| │ 单个 CPU 核心,时间片轮转 │ | ||
| │ │ | ||
| │ 并行 (Parallelism) │ | ||
| │ ┌───────────────────────────────────────────┐ │ | ||
| │ │ 多个任务同时执行 │ │ | ||
| │ │ ▓▓▓▓▓▓▓▓ 任务 A (核心 1) │ │ | ||
| │ │ ▓▓▓▓▓▓▓▓ 任务 B (核心 2) │ │ | ||
| │ │ ▓▓▓▓▓▓▓▓ 任务 C (核心 3) │ │ | ||
| │ └───────────────────────────────────────────┘ │ | ||
| │ 多个 CPU 核心,真正同时 │ | ||
| │ │ | ||
| └─────────────────────────────────────────────────────┘ |
### Rust 并发优势Rust 在编译时防止数据竞争!
数据竞争条件:
- 两个或以上线程同时访问同一数据
- 至少有一个线程在写入
- 没有同步机制
Rust 的所有权系统 + 类型系统 = 编译时消除数据竞争
## 创建线程
### 基本用法
```rust
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(10));
}
});
// 主线程工作
for i in 1..5 {
println!("主线程:{}", i);
thread::sleep(Duration::from_millis(10));
}
// 等待子线程完成
handle.join().unwrap();
println!("完成!");
}join vs detach
rust
▶ Runuse std::thread;
fn main() {
// join: 等待线程完成
let handle = thread::spawn(|| {
println!("工作中...");
});
handle.join().unwrap(); // 阻塞直到完成
// Rust 没有直接的 detach
// 但可以通过不 join 来"分离"
let _ = thread::spawn(|| {
// 不 join,线程在后台运行
});
// 注意:程序退出时,未 join 的线程会被终止
}带返回值
rust
▶ Runuse std::thread;
fn main() {
let handle = thread::spawn(|| {
let result = 42;
result // 返回值
});
// join 返回线程的返回值
let value = handle.join().unwrap();
println!("线程返回值:{}", value); // 42
}