1 个不稳定版本
使用旧的 Rust 2015
0.4.0 | 2018年3月29日 |
---|
#9 in #stm
每月 49 次下载
在 2 个包中使用 (通过 stm)
54KB
787 行
软件事务内存 
此库实现了 软件事务内存,通常缩写为 STM。
其设计紧密遵循 Haskell 的 STM 库。阅读 Simon Marlow 的 Parallel and Concurrent Programming in Haskell 获取更多信息。特别是关于 性能 的章节对于在 Rust 中使用 STM 也非常重要。
与锁不同,软件事务内存是可组合的。它通常通过在日志中编写所有读取和写入操作来实现。当操作完成且所有使用的 TVar
保持一致时,写入作为一个单一的原子操作提交。否则,计算会重复。这可能会导致饥饿,但避免了常见的错误来源。
与锁不同,软件事务内存不会在 panic 时提交。STM 通过从不提交 panic 来确保一致性。
在 STM 中 panic 不会污染 TVar
。STM 通过从不提交 panic 来确保一致性。
用法
您应仅使用可安全使用的函数。
除了来自此库的原子变量之外,不要有副作用。特别是软件事务内存中的互斥锁或其他阻塞机制是危险的。
您可以通过调用 atomically
来运行顶层原子操作。
use stm::atomically;
atomically(|trans| {
// some action
// return value as `Result`, for example
Ok(42)
});
atomically
的调用不应嵌套。
要在一个原子操作内部运行另一个原子操作,传递一个 Transaction
的可变引用,并在结果上调用 try!
或使用 ?
。您不应自己处理错误,因为这会破坏一致性。
use stm::{atomically, TVar};
let var = TVar::new(0);
let x = atomically(|trans| {
var.write(trans, 42)?; // Pass failure to parent.
var.read(trans) // Return the value saved in var.
});
println!("var = {}", x);
STM 安全性
在 Rust 考虑安全的意义上,软件事务内存是完全安全的。尽管如此,在使用软件事务内存时,您仍应遵守多个规则。
- 不要运行有副作用的代码,尤其是没有IO的代码,因为stm在检测到不一致的状态时会重复计算。如果必须,请返回一个闭包。
- 除非你完全清楚自己在做什么,否则不要自己处理错误类型。使用
Transaction::or
来组合替代路径。始终调用try!
或?
,永远不要忽略StmResult
。 - 不要在另一个
atomically
内部运行。因为atomically
设计用于有副作用,所以它会破坏stm的假设。嵌套调用会在运行时被检测到,并以panic的方式处理。当你在函数的内部使用STM时,通过将&mut Transaction
作为参数并返回StmResult<T>
来在公共接口中表达它。调用者可以安全地将它组合成更大的块。 - 不要混合锁和事务。你的代码很容易在不可预测的情况下死锁或变慢。
- 不要使用内部可变性来更改
TVar
的内容。
速度
通常尽量保持你的原子块尽可能小,因为花费的时间越多,与其他线程发生冲突的可能性就越大。对于STM,读取TVar
相当慢,因为每次都需要在日志中查找。每个使用的TVar
都会增加冲突的机会。因此,你应该将访问变量的数量保持在所需的最小范围内。
许可证
根据您的选择,许可如下
- Apache License,版本2.0,(LICENSE-APACHE或https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT许可证(LICENSE-MIT或https://open-source.org.cn/licenses/MIT)
任选其一。
贡献
除非你明确声明,否则根据Apache-2.0许可证定义的,你故意提交的任何贡献,都应按上述方式双许可,不附加任何额外条款或条件。
依赖关系
~1MB
~15K SLoC