Rust 并发与多线程:从入门到精通

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Rust 并发与多线程:从入门到精通



现代应用程序越来越需要高效利用多核处理器。Rust 提供了一种独特的并发与多线程方法,将高性能与编译阶段的内存安全保证相结合。在本文中,我们将解析关键概念:从创建线程到使用互斥锁和通道,并附有实际代码示例。



1. 多线程基础:创建和管理线程



在 Rust 中,线程通过标准库 std::thread 创建。每个线程独立执行,但可以与其他线程交换数据。



创建线程的简单示例:



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(1)); } });

for i in 1..5 { println!("主线程:数字 {}", i); thread::sleep(Duration::from_millis(1)); }

handle.join().unwrap(); // 等待线程结束}


关键点:

  • thread::spawn 接受一个闭包,该闭包在新线程中执行。
  • join 方法阻塞当前线程,直到指定线程完成。
  • 如果没有 join,主线程可能会在子线程之前结束。


要在线程之间传递数据,请使用带有 move 的闭包:



use std::thread;

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

let handle = thread::spawn(move || { println!("线程中的数据:{:?}", data); });

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


关键字 move 将数据所有权转移到闭包中,从而在编译阶段防止数据竞争。



2. 安全数据共享:互斥锁和锁



当多个线程访问共享数据时,存在数据竞争的风险。Rust 通过互斥锁(Mutex)和原子类型解决了这个问题。



使用 Mutex 和 Arc(原子引用计数)的示例:



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!("结果:{}", *counter.lock().unwrap()); // 10}


重要细节:

  • Arc<T> 允许多个线程拥有同一数据的所有权(原子克隆)。
  • Mutex::lock() 返回一个锁;如果锁已被占用,线程会等待。
  • 锁在离开作用域时自动释放。


要获得更精细的控制,请使用 RwLock,它将读者和写者分开:



use std::sync::RwLock;

let lock = RwLock::new(5);

// 读取:多个线程同时进行{ let r1 = lock.read().unwrap(); let r2 = lock.read().unwrap(); println!("读取:{} 和 {}", r1, r2);}

// 写入:仅一个线程{ let mut w = lock.write().unwrap(); *w += 1; println!("写入:{}", w);}


3. 用于消息传递的通道



共享内存的替代方案是使用通道的 Actor 模型。Rust 提供了多生产者、单消费者通道(mpsc)。



基本示例:



u                

博客

书籍推荐