`mem :: swap`ing`Mutex <T>`真的安全吗?

Mat*_* M. 6 rust

一个简单的例子:

use std::mem;
use std::sync::{Mutex};

fn main() {
    let mut orig = Mutex::new(vec![1, 2, 3]);
    let mut other = Mutex::new(vec![]);
    mem::swap(&mut orig, &mut other);
    println!("{:?}", other);
}
Run Code Online (Sandbox Code Playgroud)

据Rust说,这个程序非常安全.然而,swap(或replace)的实现并不试图锁定任何东西.从来源:

#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn swap<T>(x: &mut T, y: &mut T) {
    unsafe {
        // Give ourselves some scratch space to work with
        let mut t: T = uninitialized();

        // Perform the swap, `&mut` pointers never alias
        ptr::copy_nonoverlapping(&*x, &mut t, 1);
        ptr::copy_nonoverlapping(&*y, x, 1);
        ptr::copy_nonoverlapping(&t, y, 1);

        // y and t now point to the same thing, but we need to completely
        // forget `t` because we do not want to run the destructor for `T`
        // on its value, which is still owned somewhere outside this function.
        forget(t);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用非同步访问MutexAtomic变量似乎是一个麻烦的方法,这样安全吗?如果是,为什么?

Seb*_*edl 8

Mutexis Sync,这意味着允许多个线程同时访问同一个对象.首先可以跨线程共享单个对象的类型(Arc以及全局变量)需要确保它们共享的对象是Sync为了确保完整性.

但是,这并不能避免Rust的其他别名规则.具体来说,mut在任何给定时间只能存在一个变量的借位,并且它的存在必须阻止对该变量的任何其他访问.使分享成为可能的事情也必须确保这一点.Arc通过简单地永远不会分发mut对其指针的引用来做到这一点; 你只能获得非mut引用.这就是为什么Mutex::lock需要&self:必须可以在非mut引用上调用它.同样,Atomic*::store所有其他操作方法都需要&self.static mut另一方面,变量只能在不安全的代码中访问,程序员负责维护保证.

mem::swap需要mut参考.当编译器允许您传递两个Mutex对象时swap,这意味着您从未与其他线程共享互斥体 - 您既不会将它们放入Arc,也不会static(不mut)或static mut(除非您处于不安全的代码中).

因此,这swap是安全的,因为你是在一个线程内完成的.