【Rust的2种线程锁 阻塞 vs 挂起】

server/2025/1/19 6:47:46/

async_std::sync::Mutexstd::sync::Mutex 之间的主要区别在于它们如何处理线程阻塞和异步编程模型。以下是两者的关键差异:

标准库的 Mutex (std::sync::Mutex)
  1. 同步阻塞:当一个线程尝试获取 std::sync::Mutex 的锁时,如果锁已经被其他线程持有,调用线程将会被阻塞,直到锁变得可用。这意味着该线程将暂停执行,直到它获得锁。

  2. 线程安全std::sync::Mutex 是线程安全的,可以在多个线程之间共享,并确保同一时间只有一个线程能够访问受保护的数据。

  3. 非异步友好:由于它会阻塞线程,因此在异步环境中使用 std::sync::Mutex 可能会导致性能问题,因为被阻塞的线程不能继续执行其他任务,浪费了线程资源。

  4. 适用场景:适用于传统的多线程环境,特别是当你可以接受或需要线程阻塞的情况。

async-std 的 Mutex (async_std::sync::Mutex)
  1. 异步非阻塞async_std::sync::Mutex 设计为与异步/等待(async/await)模式一起工作。当一个任务尝试获取锁时,如果锁不可用,该任务不会阻塞线程,而是会被挂起(suspended),允许其他任务在同一线程上运行。一旦锁变为可用,任务就会被唤醒并继续执行。

    线程阻塞(Blocked)和线程挂起(Suspended)的主要区别在于原因和恢复机制:

    • 线程阻塞:线程因为等待某个事件(如 I/O 操作完成、锁的释放等)而暂停执行,不能立即继续运行。阻塞的线程通常会进入等待队列,直到它等待的事件发生
    • 线程挂起:线程被人为地暂停执行,但不是因为等待某个外部事件。挂起可以是由于调度器决定让其他线程运行,或者是由程序显式调用某些 API 使当前线程暂停。挂起的线程可以在任何时候由系统 或程序恢复。
  2. 线程安全:同样,async_std::sync::Mutex 也是线程安全的,可以在多个线程中共享,保证同一时间只有一个任务可以访问受保护的数据。

  3. 异步友好:它是专门为异步编程设计的,避免了因等待锁而导致的任务阻塞,使得线程可以更高效地利用起来。

  4. 适用场景:适用于异步编程环境,特别是在你使用 async-std 或者其他的异步运行时来构建高并发应用程序时。

使用
std::sync::Mutex
rust">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_clone = Arc::clone(&counter);let handle = thread::spawn(move || {let mut num = counter_clone.lock().unwrap();*num += 1;});handles.push(handle);}for handle in handles {handle.join().unwrap();}println!("Final counter value: {}", *counter.lock().unwrap());
}
async_std::sync::Mutex
rust">use async_std::sync::{Arc, Mutex};
use async_std::task;#[async_std::main]
async fn main() {let counter = Arc::new(Mutex::new(0));let mut handles = vec![];for _ in 0..10 {let counter_clone = Arc::clone(&counter);let handle = task::spawn(async move {let mut num = counter_clone.lock().await;*num += 1;});handles.push(handle);}for handle in handles {handle.await;}println!("Final counter value: {}", *counter.lock().await);
}
总结

选择 std::sync::Mutex 还是 async_std::sync::Mutex 主要取决于你的应用是否采用了异步编程模型。如果你的应用是基于异步/等待模式构建的,并且你希望避免因锁竞争导致的任务阻塞,那么你应该选择 async_std::sync::Mutex。对于传统的多线程应用,或者当你不介意线程阻塞时,std::sync::Mutex 仍然是一个合适的选择。


http://www.ppmy.cn/server/159563.html

相关文章

数字化时代,传统代理模式的变革之路

在数字化飞速发展的今天,线上线下融合(O2O)成了商业领域的大趋势。这股潮流,正猛烈冲击着传统代理模式,给它带来了新的改变。 咱们先看看线上线下融合现在啥情况。线上渠道那是越来越多,企业纷纷在电商平台…

一文读懂单片机的串口

目录 串口通信的基本概念 串口通信的关键参数 单片机串口的硬件连接 单片机串口的工作原理 数据发送过程 数据接收过程 单片机串口的编程实现 以51单片机为例 硬件连接 初始化串口 发送数据 接收数据 串口中断服务函数 代码示例 单片机串口的应用实例 单片机与…

第十二章:算法与程序设计

文章目录: 一:基本概念 1.算法与程序 1.1 算法 1.2 程序 2.编译预处理 3.面向对象技术 4.程序设计方法 5.SOP标志作业流程 6.工具 6.1 自然语言 6.2 流程图 6.3 N/S图 6.4 伪代码 6.5 计算机语言 二:程序设计 基础 1.常数 …

百度热力图数据原理,处理及论文应用9

目录 0、数据简介0、示例数据1、百度热力图数据日期如何选择1.1、其他实验数据的时间1.2、看日历1.3、看天气 2、百度热力图几天够研究?部分文章统计3、数据原理3.1.1 ** 这个比较重要,后面还会再次出现。核密度的值怎么理解?**3.1.2 Csv->…

Asp.Net Core 8.0 使用 Serilog 按日志级别写入日志文件的两种方式

1、所需的Nuget包 本文项目的版本是.NET 8.0,如果使用其它版本安装适配版本即可。 Serilog.AspNetCore(8.0.2) Serilog.Sinks.File(5.0.0) Serilog.Expressions(5.0.0) 2、两种配置方式 2.1 代码形式(Program.cs) 在Program.cs文件中&am…

C++/C语言判断重复数组(zznu)⭐

问题描述 如果一个数组中不包含重复的元素&#xff0c;那么我们称这个数组是独ONE无TWO的数组。给定一个数组&#xff0c;请你判断这个数组是否是独ONE无TWO的。 输入 首先输入一个正整数n表示数组的长度&#xff08;0<n<100&#xff09;。 接下来输入n个整数&#xff08…

vue前端搭建企业级项目

一、技术选型和项目研讨会 PnpmVite Vue3 JavaScript Vue Router Ant Design Vue ESLint Stylelint Prettier pnpm 包管理工具 Vite 下一代前端开发与构建工具 快速 轻量级 按需编译 热更新 Vue3 市场主流的开发框架 Composition API JavaScript 前端3剑客之一&am…

非安全函数

在C中&#xff0c;非安全函数通常是指那些在使用时容易引发安全问题&#xff08;如缓冲区溢出等&#xff09;的函数。以下是一些常见的非安全函数&#xff1a; 字符串处理函数 strcpy()&#xff1a;用于复制字符串。如果目标字符串空间不足&#xff0c;会导致缓冲区溢出。例如…