Rust 停车场文件上写着';允许在没有RAII保护对象的情况下原始(取消)锁定';?

Rust 停车场文件上写着';允许在没有RAII保护对象的情况下原始(取消)锁定';?,rust,mutex,raii,Rust,Mutex,Raii,他们说: Mutex和RwLock允许在没有RAII保护对象的情况下进行原始解锁 Mutex和RwLock允许在没有RAII保护对象的情况下进行原始锁定 没有进一步提到这些特性,它们的含义以及如何使用它们。一些指针或示例使用了什么?Rust保证安全代码不会包含数据竞争(对同一对象的并发可变访问)。互斥锁允许线程对对象进行互斥的读/写访问,从而避免了竞争 在其他语言中,(java和C++出现)互斥体与数据没有明确的关联。由程序员来确保他们正确地锁定和解锁它们,只访问锁定和解锁之间的关键部分内的数据

他们说:

  • Mutex
    RwLock
    允许在没有RAII保护对象的情况下进行原始解锁
  • Mutex
    RwLock
    允许在没有RAII保护对象的情况下进行原始锁定

  • 没有进一步提到这些特性,它们的含义以及如何使用它们。一些指针或示例使用了什么?

    Rust保证安全代码不会包含数据竞争(对同一对象的并发可变访问)。互斥锁允许线程对对象进行互斥的读/写访问,从而避免了竞争

    在其他语言中,(java和C++出现)互斥体与数据没有明确的关联。由程序员来确保他们正确地锁定和解锁它们,只访问锁定和解锁之间的关键部分内的数据。在Rust中,这意味着如果编写错误,安全代码可能包含数据竞争

    解决这个问题的办法是使用RAII防护装置。互斥体“拥有”关联的对象,只允许通过代表互斥体锁的RAII保护进行读/写访问。这是std返回的
    MutexGuard
    类型

    Parking_lot声称允许在不创建RAII防护的情况下进行锁定/解锁,这在编写不安全代码时非常有用,因为速度原因,它可以使用互斥锁执行奇特的操作。这与std的
    sync::Mutex
    不同,后者不提供这些方法

    RAII防护的主要限制是,根据RAII的性质,它们只能维持封闭范围内的时间。此外,它们持有对互斥体的引用,因此由于Rust的借用规则,“存储”超过其作用域的“锁”是很困难的


    参考的停车场方法是不安全的
    raw\u解锁
    和安全的
    raw\u锁
    。由于
    raw\u lock()
    需要关联的
    raw\u unlock()
    来完成关键部分,因此使用这些功能意味着深入研究不安全的代码,除非您有充分的理由相信这是实现所需的唯一方法,否则这通常是不明智和不必要的。

    互斥体API通过一个防护装置控制对其数据的访问,该防护装置在超出范围时解锁互斥体。
    Mutex
    拥有自己的数据,并且可以强制规定只有在锁定时才能通过
    MutexGuard
    访问数据。
    std::sync::Mutex
    停车场::Mutex
    在这方面是相同的

    但是,
    parking\u lot::Mutex
    也公开了它的内部结构,即指向数据的原始指针和
    RawMutex
    RawMutex
    只是一个锁,它不控制对数据的访问,只跟踪锁的状态

    使用
    RawMutex
    的一个原因可能是,在范围内保留
    MutexGuard
    非常不方便,并且您准备自己管理锁状态的时候。这更可能是在定义新同步原语或智能指针的库中,而不是在应用程序代码中,但是如果您机械地将现有的C/C++代码转换为Rust,您也可能会发现它很有用

    举一个简单的例子,这些函数彼此做相同的事情,但其中一个使用不安全的
    RawMutex

    use parking_lot::{Mutex, lock_api::RawMutex as _};
    
    fn update_mutex(mutex: &Mutex<i32>) {
        let mut guard = mutex.lock();
        *guard = 2;
        // guard goes out of scope here, causing the Mutex to be unlocked
    }
    
    fn update_mutex_raw(mutex: &Mutex<i32>) {
        let raw_mutex = unsafe { mutex.raw() };
        let data = mutex.data_ptr();
        raw_mutex.lock();
        unsafe { 
            *data = 2;
            // need to manually unlock the RawMutex
            raw_mutex.unlock();  
        };
    }
    
    使用停车场::{Mutex,lock_api::RawMutex as};
    fn更新\u互斥体(互斥体:&互斥体){
    让mut-guard=mutex.lock();
    *防护罩=2;
    //guard在此超出范围,导致互斥锁被解锁
    }
    fn更新\u互斥体\u原始(互斥体:&互斥体){
    让raw_mutex=unsafe{mutex.raw()};
    让data=mutex.data_ptr();
    raw_mutex.lock();
    不安全{
    *数据=2;
    //需要手动解锁RawMutex
    raw_mutex.unlock();
    };
    }
    
    RawMutex.unlock()
    是不安全的,因为当murex未锁定时,它会触发调用它的未定义行为。同时两次取消对数据指针的引用也是未定义的行为,因此您可以通过遵守
    RawMutex
    的锁定状态来确保您没有这样做


    与往常一样,在使用不安全的函数时,请仔细阅读文档,并确保您彻底理解了为避免未定义的行为而必须保留的不变量。

    可能指的是不安全的和安全的,后者仅在
    Mutex
    上可用。如果停车场的
    Mutex
    RawMutex
    之间有任何性能差异,我会非常惊讶。同意。它不会在单个操作中产生性能差异,而是通过在与单个RAII guard不兼容的模式中锁定和解锁,从而减少锁定和解锁的数量或保留某些其他属性。