The 锈书讨论了拥有多个读取器和对一个对象的多个可变引用作为可能导致问题的数据竞争情况。
例如,这段代码:
fn main() {
let mut x = 1;
let r1 = &mut x;
*r1 = 2;
let r2 = &mut x;
*r2 = 3;
println!("{}", r1);
println!("{}", r2);
}
将被 Rust 编译器拒绝,因为r1
and r2
范围是相互交织的。
但这里有什么问题呢?我的意思是,这只是一个线程,并且没有“同时读写”,因此所有这些语句都应该严格按顺序执行,并给出确定性的可重现结果。
From 尼科·马萨基斯的博客:
我经常认为,虽然技术意义上的数据争用只能发生在并行系统中,但问题feel就像顺序系统中不断出现的数据竞争一样。一个例子是 C++ 民间所说的迭代器失效—基本上,如果您迭代哈希表并尝试在迭代期间修改哈希表,则会得到未定义的行为。有时您的迭代会跳过键或值,有时会显示新键,有时不会,等等。
但无论结果如何,迭代器失效感觉与数据竞争非常相似。这个问题经常出现,因为你有一段代码迭代哈希表,然后调用在其他模块中定义的子例程。然后,另一个模块写入同一个哈希表。这两个模块本身看起来都很好,只有两者的组合才会导致问题。由于结果的不确定性,代码经常会在很长一段时间内正常工作,直到出现问题为止。
Rust 的类型系统可以防止迭代器失效。
Rust 的类型系统不允许像下面这样的单线程程序进行编译,因为它们会导致未定义的行为,而从技术上讲,这不是一场数据竞赛这个特殊的错误与“由两段独立的代码以交织的方式改变相同数据引起的错误”属于同一范围,因此它与数据竞争非常相似,我相信这就是 Rust 书试图传达的内容:
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert(1, 1);
map.insert(2, 2);
map.insert(3, 3);
for _ in map.iter() {
map.insert(4, 4); // compile error!
}
}
操场
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)