美文网首页
Rust for cpp devs - 线程

Rust for cpp devs - 线程

作者: 找不到工作 | 来源:发表于2021-05-19 20:41 被阅读0次

由于 Rust 特有的 ownership 和类型检查机制,许多并发问题都可以在编译期发现,这极大地降低了风险以及 debug 难度。因此,Rust 这个特性被称为“无畏的并发”。

Thread

由于 Rust runtime 比较简单,因此 Rust 标准库只实现了系统级线程(thread),而没有实现用户级线程(coroutine)。

使用 spawn 创建线程

spawn 方法接收一个可执行的 closure,开启一个新的线程并开始执行这个 closure:

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

输出结果是:

hi number 1 from the main thread!
hi number 1 from the spawned thread!
hi number 2 from the main thread!
hi number 2 from the spawned thread!
hi number 3 from the main thread!
hi number 3 from the spawned thread!
hi number 4 from the main thread!
hi number 4 from the spawned thread!
hi number 5 from the spawned thread!

我们发现,新建的线程中的函数并没有执行完毕。这是因为 spawn 创建的线程默认是 detach 运行的,我们需要 join 这个新的线程。

实际上,spawn 函数会返回一个 JoinHandle,它提供了一个 join 方法,保证在 join 过后该线程的操作全部完成。

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

fn main() {
    let join_handle = 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_handle
        .join()
        .expect("Couldn't join on the associated thread");
}

输出结果是:

hi number 1 from the main thread!
hi number 1 from the spawned thread!
hi number 2 from the main thread!
hi number 2 from the spawned thread!
hi number 3 from the main thread!
hi number 3 from the spawned thread!
hi number 4 from the main thread!
hi number 4 from the spawned thread!
hi number 5 from the spawned thread!
hi number 6 from the spawned thread!
hi number 7 from the spawned thread!
hi number 8 from the spawned thread!
hi number 9 from the spawned thread!

使用 move 关键字

有时候,我们需要在新的线程中使用当前环境的变量,比如下面的例子,我们希望能在另一个线程打印这个数组:

fn use_move() {
    let v = vec![1, 2, 3];
    let handle = thread::spawn(|| {
        println!("Here's a vector: {:?}", v);
    });
    handle
        .join()
        .expect("Couldn't join on the associated thread");
}

编译报错:

error[E0373]: closure may outlive the current function, but it borrows `v`, which is owned by the current function
  --> src/main.rs:24:33
   |
24 |     let handle = thread::spawn( || {
   |                                 ^^ may outlive borrowed value `v`
25 |         println!("Here's a vector: {:?}", v);
   |                                           - `v` is borrowed here
   |
note: function requires argument type to outlive `'static`

因为 closure 中只有 println!,因此捕获变量时只采用了“常值引用”方式,然而,Rust 无法知道子线程会运行多久,因此无法确定 v 是否能全程保持有效。

此时,如同我们在 Rust for cpp devs - closure 中讲的,我们可以使用 move 关键字强制 closure 拿走 v 的 ownership。

fn use_move() {
    let v = vec![1, 2, 3];
    let handle = thread::spawn(move || {  // add 'move' here
        println!("Here's a vector: {:?}", v);
    });

    handle
        .join()
        .expect("Couldn't join on the associated thread");
}

相关文章

  • Rust for cpp devs - 线程

    由于 Rust 特有的 ownership 和类型检查机制,许多并发问题都可以在编译期发现,这极大地降低了风险以及...

  • Rust for cpp devs - mutex

    除了 channel[https://www.jianshu.com/p/925d3534ac7f],我们也可以通...

  • Rust for cpp devs - Ownership

    编程语言的内存管理一般有两种: 带垃圾回收机制的,如 Java,Golang,会在运行时检查不再使用的内存并回收,...

  • Rust for cpp devs - channel

    与 golang 一样,Rust 也实现了 channel 用于线程间的通信。如同 golang 的口号一样: D...

  • Rust for cpp devs - closure

    类似于 cpp 中的 lambda 表达式,Rust 中也有 closure。他们与普通函数的区别在于可以捕获变量...

  • Rust for cpp devs - Generic Type

    类似于 cpp,Rust 中也有泛型(generics),用于避免重复的代码。此外,还可以指定 traits 来限...

  • Rust for cpp devs - 迭代器

    迭代器(Iterator)可以允许对序列中的每一个元素执行某个操作。 Rust 的迭代器分为三种: iter() ...

  • Rust for cpp devs - minigrep 项目

    官方文档用 minigrep 项目来讲解如何组织一个 Rust 项目。 保持 main 函数简洁 这样做的好处是:...

  • Rust for cpp devs - 错误处理

    Rust 将软件中的错误分为两个类型:可恢复错误和不可恢复错误。 对于可恢复错误,例如文件找不到,可以报告给调用者...

  • Rust for cpp devs - 生命周期

    生命周期(lifetime)也是一类泛型。但它是用于指定引用保持有效的作用域。 Rust 中的每个引用都有相应的 ...

网友评论

      本文标题:Rust for cpp devs - 线程

      本文链接:https://www.haomeiwen.com/subject/afbyjltx.html