Day 10 - 无畏并发

本贴最后更新于 595 天前,其中的信息可能已经沧海桑田

image

Concurrent: 程序的不同部分之间独立的运行;【并发 独立】

Parallel: 程序的不同部分同时运行;【并行 同时】

img

📚 无畏并发

创建时间:2023-04-07 01:17 星期五


定义

在 Rust 中的并发就是允许你编写没有**细微 Bug(比如死锁问题)**的代码并在不引入新 Bug 的情况下易于重构。

Rust 的“无畏并发”(Fearless Concurrency)是指在编写并发程序时,Rust 编程语言提供了安全而高效的工具和抽象,使得程序员能够轻松地编写出正确且高效的并发代码,而不必担心并发常见的问题,例如竞态条件(Race conditions)、死锁(Deadlocks)等。

具体来说,Rust 的无畏并发指的是:

  1. Rust 提供了类型系统和所有权模型,可以在编译时检测出数据竞争(Data race)等并发错误,并且确保多线程操作时只有一个线程可以修改共享数据。
  2. Rust 的标准库提供了许多高级并发原语和抽象,例如锁(Locks)、通道(Channels)、原子类型(Atomic types)等,可以轻松地编写出高效且安全的并发代码。
  3. Rust 的编译器能够智能地推断出代码中的并发问题,并给出有用的错误信息和建议,使得程序员能够快速发现和修复潜在的并发问题。

总的来说,Rust 的无畏并发使得程序员可以在不失安全性和性能的前提下,轻松地编写高效的并发代码,而不必担心并发带来的种种问题。

使用线程同时运行代码

进程线程 数据竞争和死锁问题你需要进行了解 这里默认你都会这些了

用户级线程以及系统级线程

用户级线程和操作系统级线程是两个概念。用户级线程通常也称为轻量级线程、协程或绿色线程,是由用户程序自己实现的线程模型,与操作系统无关。而操作系统级线程通常也称为重量级线程或内核线程,是由操作系统内核来实现的线程模型,需要操作系统的支持

用户级线程和操作系统级线程之间的关系可以分为两种模型:1:1 线程模型N:M 线程模型。在 1:1 线程模型中,每个用户级线程都直接映射到一个操作系统级线程上而在 N:M 线程模型中,多个用户级线程被映射到少量的操作系统级线程上

1:1 线程模型中,用户级线程的创建、销毁、同步和通信等操作都由操作系统来管理和实现,这使得线程的执行更加可靠和稳定,同时也带来了一定的开销和限制。相比之下,在 N:M 线程模型中,用户级线程的创建、销毁、同步和通信等操作都由用户空间的线程库来管理,这使得线程的创建和销毁等操作更加高效,同时也带来了更灵活的线程调度和管理方式

总的来说,用户级线程是由用户程序自己实现的线程模型,它们与操作系统无关,而操作系统级线程是由操作系统内核来实现的线程模型,需要操作系统的支持。用户级线程和操作系统级线程之间的关系可以采用不同的模型进行映射,以达到不同的优化目标和应用场景。

更多类型的线程

实现线程的方式

运行时

编程语言的运行时(Runtime)是指该语言的一组库、环境和其他支持程序,这些程序在代码运行期间提供了必要的支持和服务。运行时可以看做是一个框架或平台,提供了诸如内存管理、类型检查、异常处理、并发控制、IO、网络通信等常见功能的实现,同时为程序员提供了一系列的 API,使得程序员可以方便地调用这些服务和功能,从而编写高效且可靠的代码。

编程语言的运行时通常由编译器或解释器自动构建和管理,这些工具会将运行时的支持库和其他相关资源打包到可执行程序或库文件中,以便在运行时使用。运行时通常是编程语言的核心部分,直接影响着程序的性能、可靠性和安全性等方面。例如,Java 的运行时环境(JRE)提供了 Java 程序运行所需的核心库、虚拟机和其他资源,而 Python 的运行时则包括解释器、标准库和其他支持程序。

  • 通过 OS 的 API 创建线程: 1:1 模型【 需要比较小的运行时】

    • 利用 OS 的内核提供支持
  • 通过语言自己实现的线程: M:N 模型【需要更大的运行时】

我们的标准库只提供了 1:1 的线程(也就是让线程的操作交给 OS 的 API 进行处理)

use std::{thread, time::Duration};

fn main() {
    thread::spawn(||{
        for i in 1..1000{
            println!("子 {i}");
            thread::sleep(Duration::from_millis(1)); // 子线程需要休息一毫秒
        }
    });
    for i in 1..120{
        println!("主 {i}");
        thread::sleep(Duration::from_millis(1)); // 主线程也需要休息一毫秒

    }
}

我们使用 thread::spaw 进行线程的创建传入一个闭包。我们发现只要主线程执行完毕子线程也会直接结束无论子线程有没有执行完毕,他们也是交替出现的。

当然我们可以使用 JoinHandle 让主线程等待子线程的执行

use std::{thread::{self, JoinHandle}, time::Duration, slice::Join};

fn main() {
    let joinHandler:JoinHandle<()> = thread::spawn(||{
        for i in 1..1000{
            println!("子 {i}");
            thread::sleep(Duration::from_millis(1)); // 子线程需要休息一毫秒
        }
    });

    for i in 1..40{
        println!("主 {i}");
        thread::sleep(Duration::from_millis(1)); // 主线程也需要休息一毫秒
    }

    joinHandler.join().expect("有错误!"); // 阻塞
}

Move 闭包和线程

move 可以让我们把值转移到另外一个线程中.

use std::{thread::{self, JoinHandle}, time::Duration};

fn main() {
    let v = 3;
    let joinHandler:JoinHandle<()> = thread::spawn(move ||{
        for i in 1..1000{
            println!("子:{i} 还有父亲的v:{v}");
            thread::sleep(Duration::from_millis(1)); // 子线程需要休息一毫秒
        }
    });

    for i in 1..40{
        println!("主 {i}");
        thread::sleep(Duration::from_millis(1)); // 主线程也需要休息一毫秒
    }

    joinHandler.join().expect("有错误!");
}

消息

你可能会了解消息队列这种技术,比如:RabbitMQ/Kafka, 在 Rust 中,我们就可以使用消息,让线程之间彼此发送数据以便达到数据通信。在 Rust 中,消息是 多生产者一消费者的模式​.

使用 mpsc::channel​函数进行的创建他会返回一个元组里面的元素是发送端和接收端。

use std::thread as thread;
use std::sync::mpsc::channel as channel;

fn main(){
    let (sender,recver) = channel();
    let sender_thread = thread::spawn(move ||{
        let a = "24";
        sender.send(String::from(format!("我发送数据啦, 并且我准备好了一个数据{a}")))
		.expect("我不能发送消息");
    });

    let ret = recver.recv().expect("我收不到你的数据");

    sender_thread.join().expect("子线程无法被等待");
    println!("子线程的数据是:{}",ret)
}

**注意 send 会移动传入参数的所有权!**当接收端被丢弃 send 会报错。 recv 会阻塞当前线程直到发现了值。当然 try_recv 不会

如果接收端会收到发送端多次的值 这个时候我们可以吧 recver​ 当成迭代器使用

for i in recver{
	println!("{i}");
}

共享状态的并发

【反正我是不推荐这么做的】

使用同一个内存进行数据的共享,也就是经典的读写内存互斥锁。

通过 Send 和 SyncTrait 来扩展并发

image上述的两个特性其实是一个 也就是不存在任何的方法。

image

  • Rust

    Rust 是一门赋予每个人构建可靠且高效软件能力的语言。Rust 由 Mozilla 开发,最早发布于 2014 年 9 月。

    58 引用 • 22 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...