13次发布
使用旧的Rust 2015
0.4.0 | 2020年10月6日 |
---|---|
0.3.5 | 2018年5月5日 |
0.3.4 | 2015年6月7日 |
#234 in Rust模式
6,016每月下载
在 80 个crate中使用 (7 直接使用)
86KB
298 行
Atom
Atom
是Rust的 AtomicPtr
的简单抽象。它提供了一个简单、无等待的方式来在线程之间安全地交换数据。 Atom
依赖于原子交换可以用来安全地模拟Rust的所有权。
在Rust中(或任何语言),使用 store
来设置共享原子指针是不安全的,因为指针的内容可能在任何时候被覆盖,导致指针内容丢失。这可能导致你的系统泄漏内存,如果你期望该内存执行某些有用的操作(如唤醒休眠线程),你将陷入麻烦。
同样,load
也是不安全的,因为没有保证你在读取之后该指针甚至能存活一个周期。另一个线程可能会修改该指针,或者释放它。为了使 load
安全,你需要有一些外部协议来保留正确的所有权语义。
swap
是特殊的,因为它允许交换引用而不存在指针被释放或破坏的风险。当一个线程交换 AtomicPtr
时,旧的指针所有权会移动到调用者,而 AtomicPtr
会获得新的指针的所有权。
使用 Atom
将atom添加到你的 Cargo.toml
[dependencies]
atom="*"
一个简短的例子
extern crate atom;
use std::sync::Arc;
use std::thread;
use atom::*;
fn main() {
// Create an empty atom
let shared_atom = Arc::new(Atom::empty());
// set the value 75
shared_atom.swap(Box::new(75));
// Spawn a bunch of thread that will try and take the value
let threads: Vec<thread::JoinHandle<()>> = (0..8).map(|_| {
let shared_atom = shared_atom.clone();
thread::spawn(move || {
// Take the contents of the atom, only one will win the race
if let Some(v) = shared_atom.take() {
println!("I got it: {:?} :D", v);
} else {
println!("I did not get it :(");
}
})
}).collect();
// join the threads
for t in threads { t.join().unwrap(); }
结果将类似于这样
I did not get it :(
I got it: 75 :D
I did not get it :(
I did not get it :(
I did not get it :(
I did not get it :(
I did not get it :(
I did not get it :(
使用 Atom
比使用原始的 AtomicPtr
有一些优势。首先,您不需要任何不安全代码就可以将 Box<T>
转换为和从 Box
,库会为您处理这些。其次,Atom
实现了 drop
,所以您在丢弃数据结构时不会意外地泄漏指针。
AtomSetOnce
这是对 Atom 的一种额外抽象。回想一下,我说过除非您有额外的限制,否则 load
是不安全的。AtomSetOnce
如其名称所示,可能只能设置一次,然后它可能永远不会被重置。我们知道如果 Atom 被设置,指针将保持有效直到 Atom 的生命周期结束。这意味着我们可以安全地实现 Deref
。
查看 fifo
示例,了解如何使用它来编写无锁链表。