28_rust_无畏并发

发布时间 2023-11-18 17:03:12作者: 00lab

无畏并发

Concurrent:程序不同部分之间独立执行;
Parallel:程序不同部分同时运行。

rust无畏并发:允许编写没有细微Bug的代码。并在不引入新Bug的情况下易于重构。这里所说的“并发”泛指concurrent和parallel。

使用线程同时运行代码

1:1模型:实现线程的方式:通过调用OS的API创建线程。只需较小的运行时。
M:N模型:语言自己实现的线程(绿色线程),需要更大的运行时。
rust:需要权衡运行时的支持,希望尽可能小的运行时支持。rust标准库仅提供1:1模型的线程。

通过spawn创建新线程
通过thread::spawn函数可创建新线程,参数是一个闭包(即在新线程里运行的代码)。
thread::sleep可让当前线程暂停执行。

use std::thread;
use std::time::Duration;

fn main() {
    thread::spawn(|| {
      for i in 1..10 {
          println!("spawn thread {}", i);
          thread::sleep(Duration::from_millis(1));
      }
    });
    for i in 1..5 {
        println!("main thread {}", i);
        thread::sleep(Duration::from_millis(1));// sleep 1ms
    }
}
/* 输出结果
main thread 1
spawn thread 1
main thread 2
spawn thread 2
spawn thread 3
main thread 3
main thread 4
spawn thread 4
*/

可看出,主线程结束时,子线程也结束。
通过join Handle来等待所有线程完成
thread::spawn函数返回值类型时JoinHandle,JoinHandle持有值的所有权。调用join方法,可等待对应其它线程完成。

  • join方法:调用handle的join方法会阻止当前运行线程的执行,直到handle所表示的这些线程终结。
use std::thread;
use std::time::Duration;

fn main() {
    let handle = thread::spawn(|| {
      for i in 1..10 {
          println!("spawn thread {}", i);
          thread::sleep(Duration::from_millis(1));
      }
    });
    for i in 1..5 {
        println!("main thread {}", i);
        thread::sleep(Duration::from_millis(1));// sleep 1ms
    }
    handle.join().unwrap(); // 会阻止主线程执行,直到子线程结束 
}
/*输出
main thread 1
spawn thread 1
spawn thread 2
main thread 2
spawn thread 3
spawn thread 4
main thread 3
main thread 4
spawn thread 5
spawn thread 6
spawn thread 7
spawn thread 8
spawn thread 9
*/

如果将handle.join().unwrap()提前到主函数的打印之前,可看到主函数的打印会在子线程执行完之后。