在哪些情况下 Arc<Mutex<T>> 不是 Rust 中跨线程共享数据的最佳方式?

phi*_*611 6 rust

根据我的了解,我应该始终选择Arc<T>跨线程共享读访问和跨线程Arc<Mutex<T>>共享写访问。在某些情况下,我不想使用Arc<T>/Arc<Mutex<T>>而是做一些完全不同的事情吗?例如做这样的事情:

unsafe impl Sync for MyStruct {}
unsafe impl Send for MyStruct {}

let shared_data_for_writing = Arc::from(MyStruct::new());
Run Code Online (Sandbox Code Playgroud)

Fra*_*gné 7

跨线程共享

此外Arc<T>,我们可以使用作用域线程跨线程共享对象,例如使用crossbeam::scopeScope::spawn。作用域线程允许我们将借用的指针 ( &'a T)发送到作用域中产生的线程。范围保证线程将在引用对象被删除之前终止。与Arc<T>(Arc<T>占用更多内存并需要使用原子指令维护引用计数器)相比,借用指针没有运行时开销。

跨线程变异

Mutex<T>是最基本的通用包装器,用于确保在任何给定时间最多有一个线程可以改变一个值。Mutex<T>有一个缺点:如果有许多线程只想读取互斥锁中的值,则它们不能同时执行,即使这样做是安全的。RwLock<T>通过允许多个并发读取器(同时仍确保写入器具有独占访问权限)来解决此问题。

原子类型,例如AtomicUsize也允许跨线程变异,但仅适用于小值(8、16、32 或 64 位 - 一些处理器支持对 128 位值的原子操作,但标准库中尚未公开;请参阅atomic::Atomic) . 例如,Arc<Mutex<usize>>您可以使用来代替Arc<AtomicUsize>。原子类型不需要锁定,但它们通过原子机器指令进行操作。原子指令集与非原子指令集略有不同,因此从非原子类型切换到原子类型可能并不总是“直接替换”。