简介
本教程旨在深入探讨 Rust 语言的并发编程特性。我们将学习如何使用多个线程来提高应用程序的性能,以及如何处理共享状态和数据竞争等问题。
环境准备
- 安装 Rust: https://www.rust-lang.org/tools/install
- 文本编辑器或集成开发环境(IDE),如 Visual Studio Code, IntelliJ Rust, Eclipse等。
基础知识
什么是并发?
并发指的是同时处理多个任务的能力。它与并行不同,后者是在同一时刻执行多个操作。Rust 提供了丰富的并发支持,可以让我们编写高效、安全的多线程应用程序。
什么是线程?
线程是一个轻量级的进程,它在同一进程内共享相同的内存空间。每个线程都可以独立地执行代码,使得多任务处理成为可能。
Rust 中的并发编程
创建一个新线程
Rust 标准库提供了 std::thread
模块来支持多线程编程。下面是如何创建和执行一个新线程的示例:
use std::thread;
use std::time::Duration;
fn main() {
thread::spawn(|| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("hi number {} from the main thread!", i);
thread::sleep(Duration::from_millis(1));
}
}
等待线程完成
如果我们想要在主线程中等待新线程的执行结束,可以使用 join
方法:
use std::thread;
fn main() {
let handle = thread::spawn(|| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
}
});
handle.join().unwrap();
for i in 1..5 {
println!("hi number {} from the main thread!", i);
}
}
使用 move
关键字移动所有权
如果我们想要在新线程中使用主线程的数据,需要使用 move
关键字将所有权转移到新线程:
use std::thread;
fn main() {
let v = vec![1, 2, 3];
let handle = thread::spawn(move || {
println!("Here's a vector: {:?}", v);
});
handle.join().unwrap();
}
共享状态和数据竞争
Mutex
互斥锁(Mutual Exclusion, Mutex)是一种同步原语,它可以保证在任意时刻只有一个线程能够访问某个资源。Rust 标准库提供了 std::sync::Mutex
类型来实现互斥锁:
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", *counter.lock().unwrap());
}
RwLock
读写锁(Read Write Lock, RwLock)允许多个线程同时读取数据,但只有一个线程能够写入数据。这种机制可以提高并发性能:
use std::sync::{Arc, RwLock};
use std::thread;
fn main() {
let data = Arc::new(RwLock::new(vec![1, 2, 3]));
let mut handles = vec![];
for _ in 0..5 {
let data = Arc::clone(&data);
let handle = thread::spawn(move || {
println!("Read: {:?}", *data.read().unwrap());
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
let mut data = data.write().unwrap();
data.push(4);
}
结论
本教程介绍了 Rust 中的并发编程基础知识,包括线程创建、等待、数据移动和共享状态管理。通过掌握这些技能,我们可以编写出高效、安全的多线程应用程序。