news 2026/6/12 11:29:56

HoRain云--Rust 并发编程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HoRain云--Rust 并发编程

🎬 HoRain 云小助手:个人主页

⛺️生活的理想,就是为了理想的生活!


⛳️ 推荐

前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。

目录

⛳️ 推荐

线程

实例

实例

实例

实例

join 方法

实例

move 强制所有权迁移

实例

实例

消息传递

实例


安全高效的处理并发是 Rust 诞生的目的之一,主要解决的是服务器高负载承受能力。

并发(concurrent)的概念是指程序不同的部分独立执行,这与并行(parallel)的概念容易混淆,并行强调的是"同时执行"。

并发往往会造成并行。

本章讲述与并发相关的编程概念和细节。

线程

线程(thread)是一个程序中独立运行的一个部分。

线程不同于进程(process)的地方是线程是程序以内的概念,程序往往是在一个进程中执行的。

在有操作系统的环境中进程往往被交替地调度得以执行,线程则在进程以内由程序进行调度。

由于线程并发很有可能出现并行的情况,所以在并行中可能遇到的死锁、延宕错误常出现于含有并发机制的程序。

为了解决这些问题,很多其它语言(如 Java、C#)采用特殊的运行时(runtime)软件来协调资源,但这样无疑极大地降低了程序的执行效率。

C/C++ 语言在操作系统的最底层也支持多线程,且语言本身以及其编译器不具备侦察和避免并行错误的能力,这对于开发者来说压力很大,开发者需要花费大量的精力避免发生错误。

Rust 不依靠运行时环境,这一点像 C/C++ 一样。

但 Rust 在语言本身就设计了包括所有权机制在内的手段来尽可能地把最常见的错误消灭在编译阶段,这一点其他语言不具备。

但这不意味着我们编程的时候可以不小心,迄今为止由于并发造成的问题还没有在公共范围内得到完全解决,仍有可能出现错误,并发编程时要尽量小心!

Rust 中通过 std::thread::spawn 函数创建新线程:

实例

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

fn spawn_function() {
for i in 0..5 {
println!("spawned thread print {}", i);
thread::sleep(Duration::from_millis(1));
}
}

fn main() {
thread::spawn(spawn_function);

for i in 0..3 {
println!("main thread print {}", i);
thread::sleep(Duration::from_millis(1));
}
}

运行结果:

main thread print 0 spawned thread print 0 main thread print 1 spawned thread print 1 main thread print 2 spawned thread print 2

这个结果在某些情况下顺序有可能变化,但总体上是这样打印出来的。

此程序有一个子线程,目的是打印 5 行文字,主线程打印三行文字,但很显然随着主线程的结束,spawn 线程也随之结束了,并没有完成所有打印。

std::thread::spawn 函数的参数是一个无参函数,但上述写法不是推荐的写法,我们可以使用闭包(closures)来传递函数作为参数:

实例

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

fn main() {
thread::spawn(|| {
for i in 0..5 {
println!("spawned thread print {}", i);
thread::sleep(Duration::from_millis(1));
}
});

for i in 0..3 {
println!("main thread print {}", i);
thread::sleep(Duration::from_millis(1));
}
}

闭包是可以保存进变量或作为参数传递给其他函数的匿名函数。闭包相当于 Rust 中的 Lambda 表达式,格式如下:

|参数1, 参数2, ...| -> 返回值类型 { // 函数体 }

例如:

实例

fn main() {
let inc = |num: i32| -> i32 {
num + 1
};
println!("inc(5) = {}", inc(5));
}

运行结果:

inc(5) = 6

闭包可以省略类型声明使用 Rust 自动类型判断机制:

实例

fn main() {
let inc = |num| {
num + 1
};
println!("inc(5) = {}", inc(5));
}

结果没有变化。

join 方法

实例

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

fn main() {
let handle = thread::spawn(|| {
for i in 0..5 {
println!("spawned thread print {}", i);
thread::sleep(Duration::from_millis(1));
}
});

for i in 0..3 {
println!("main thread print {}", i);
thread::sleep(Duration::from_millis(1));
}

handle.join().unwrap();
}

运行结果:

main thread print 0 spawned thread print 0 spawned thread print 1 main thread print 1 spawned thread print 2 main thread print 2 spawned thread print 3 spawned thread print 4

join 方法可以使子线程运行结束后再停止运行程序。

move 强制所有权迁移

这是一个经常遇到的情况:

实例

use std::thread;

fn main() {
let s = "hello";

let handle = thread::spawn(|| {
println!("{}", s);
});

handle.join().unwrap();
}

在子线程中尝试使用当前函数的资源,这一定是错误的!因为所有权机制禁止这种危险情况的产生,它将破坏所有权机制销毁资源的一定性。我们可以使用闭包的 move 关键字来处理:

实例

use std::thread;

fn main() {
let s = "hello";

let handle = thread::spawn(move || {
println!("{}", s);
});

handle.join().unwrap();
}

消息传递

Rust 中一个实现消息传递并发的主要工具是通道(channel),通道有两部分组成,一个发送者(transmitter)和一个接收者(receiver)。

std::sync::mpsc 包含了消息传递的方法:

实例

use std::thread;
use std::sync::mpsc;

fn main() {
let (tx, rx) = mpsc::channel();

thread::spawn(move || {
let val = String::from("hi");
tx.send(val).unwrap();
});

let received = rx.recv().unwrap();
println!("Got: {}", received);
}

运行结果:

Got: hi

子线程获得了主线程的发送者 tx,并调用了它的 send 方法发送了一个字符串,然后主线程就通过对应的接收者 rx 接收到了。

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/12 11:21:51

Nginx缓存原理机制如何提高十倍性能

Nginx缓存的本质在入口层拦截流量,把高并发问题提前解决。在高并发场景中,系统性能瓶颈通常不在CPU,而在:数据库 IO、网络请求、后端服务响应。如果每个请求都直达数据库或后端服务,系统很快就会被拖垮。这时,Nginx的缓存机制就成了关键。把“重复请求”直接在入口层拦截…

作者头像 李华
网站建设 2026/6/12 11:15:52

遗传算法实战调参指南:选择策略、交叉变异与收敛诊断

1. 项目概述:为什么第二部分比第一部分更值得细读“遗传算法入门——第二部分”这个标题乍看平平无奇,像是某门在线课程里被跳过的中间章节。但如果你真把Part One当作“认识DNA双螺旋”,那Part Two就是亲手在培养皿里启动第一次交叉、观察种…

作者头像 李华
网站建设 2026/6/12 11:14:04

5分钟搭建安全文件共享服务:atmoz/sftp Docker镜像完全指南

5分钟搭建安全文件共享服务:atmoz/sftp Docker镜像完全指南 【免费下载链接】sftp Securely share your files 项目地址: https://gitcode.com/gh_mirrors/sf/sftp 在当今的开发和运维工作中,安全地共享文件是一个常见需求。无论是团队协作、客户…

作者头像 李华
网站建设 2026/6/12 11:11:04

终极Windows驱动管理指南:如何使用DriverStore Explorer清理系统垃圾

终极Windows驱动管理指南:如何使用DriverStore Explorer清理系统垃圾 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer Windows驱动存储管理是每个系统管理员和高级用户必须掌…

作者头像 李华