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

devtools/2025/1/19 12:42:27/

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/devtools/151811.html

相关文章

C++ QT中Q_Q和Q_D是什么?怎么使用?本质是什么?C++仿写

1.QT中Q_Q和Q_D是什么&#xff1f; Q_Q可以得到外部可以访问的类指针Q_D可以得到内部封装&#xff0c;外部不可达的类指针 2. 怎么使用&#xff1f; 上代码 APrivate.h #pragma once #include <QtCore>class A;class APrivate {Q_DECLARE_PUBLIC(A) public:APrivate(…

迅为RK3568开发板篇OpenHarmony实操HDF驱动控制LED-编写内核 LED HDF 驱动程序

接下来编译 LED 驱动&#xff0c;该驱动用于在基于华为设备框架&#xff08;HDF&#xff09;的系统中控制 LED 灯的开关&#xff0c;完整代码如下所示&#xff1a; 更多内容可以关注&#xff1a;迅为RK3568开发板篇OpenHarmony

挖掘机检测数据集,准确识别率91.0%,4327张原始图片,支持YOLO,COCO JSON,PASICAL VOC XML等多种格式标注

挖掘机检测数据集&#xff0c;准确识别率91.0%&#xff0c;4327张图片&#xff0c;支持YOLO&#xff0c;COCO JSON&#xff0c;PASICAL VOC XML等多种格式标注 数据集详情 数据集分割 训练组70&#xff05; 3022图片 有效集20&#xff05; 870图片 测试集10&…

vim练级攻略(精简版)

vim推荐配置: curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh && bash ./install.sh 0. 规定 Ctrl-λ 等价于 <C-λ> :command 等价于 :command <回车> n 等价于 数字 blank字符 等价于 空格&#xff0c;tab&am…

Wi-Fi 7、Wi-Fi 6 与 5G、4G 的全方位对比

随着无线通信技术的飞速发展&#xff0c;Wi-Fi 7、Wi-Fi 6&#xff0c;以及5G、4G 已经成为人们生活和工作中不可或缺的网络技术。无论是家庭网络、高速移动通信&#xff0c;还是工业物联网&#xff0c;这些技术都在发挥各自的作用。那么&#xff0c;它们之间有什么区别&#x…

电梯系统的UML文档05

Dispatcher 不控制实际的电梯组件&#xff0c;但它在软件系统中是重要的。每一个电梯有一个ispatcher&#xff0c;主要功能是计算电梯的移动方向、移动目的地以及保持门的打开时间。它和系统中除灯控制器以外的几乎所有控制对象交互。 安全装置也是一个环境对象&#xff0c;它…

Android wifi列表中去自身的热点

Android wifi列表中去自身的热点 一、前言 Android wifi列表中能搜索到自身的热点wifi&#xff1f; 正常手机上都不会出现这个问题&#xff1b;可能是系统底层已经做了过滤处理。 现实开发中Android设备的Wifi能搜索到自身热点也可能会存在。 比如基于两个单独的wifi双模组硬…

02UML图(D1_结构图)

目录 学习前言 ---------------------------------- 讲解一&#xff1a;类图 一、类图的组成结构 1. 类(Class) 1.1. 类的成员变量的表示方式 1.2. 类的成员方法的表示方式 2. 接口&#xff08;Interface&#xff09; 3. 包&#xff08;Package&#xff09; 二、UML类…