根据文档,
\n\n\n数据竞争会导致未定义的行为,并且当您\xe2\x80\x99尝试在运行时追踪它们时,可能很难诊断和修复;Rust 通过拒绝编译带有数据竞争的代码来防止这个问题!
\n
除非你\xe2\x80\x99re多线程,否则为什么这是一个问题?如果同时访问一个变量及其一个mut引用,\xe2\x80\x99t 这个问题是否仍然存在?
你似乎对某些事情感到困惑。
\n首先,您似乎有这样的印象:如果您可变地借用一个值,则可以通过可变引用并直接使用您借用的变量来改变该值。 这不是真的。 在借用结束之前,该变量实际上不可用:
\nfn main() {\n let mut x = 0;\n let y = &mut x;\n\n // The following line causes a compile-time error.\n // error[E0506]: cannot assign to `x` because it is borrowed\n x = 1;\n\n *y = 2;\n}\nRun Code Online (Sandbox Code Playgroud)\n最多可以有一个名称,通过该名称可以在任何给定时刻修改值。由于x被 可变地借用y,因此在借用者被释放之前,该名称x不能用于修改值y。
\n\n除非你\xe2\x80\x99re多线程,否则为什么这是一个问题?
\n
因为改变状态可能会使引用无效。
\n考虑一下您有 Vec 的情况。当 Vec 或其任何元素被借用时,您不得修改 Vec 或其任何内容,因为这是不安全的。为什么在单线程代码中会不安全?
\n如果您引用了某个项目并且该项目从 Vec 中删除了,会发生什么情况?您引用了无效值或与之前不同的值。
\n如果向 Vec 添加一个元素,但其内部数组已满,会发生什么情况?Vec 将分配一个新的、较大的数组,将较小数组中的所有元素转移到较大数组中,然后销毁较小数组。 所有先前存在的对元素的引用都将因该操作而失效。
\n这就是为什么你不能在迭代 Vec 时改变它,例如:
\nfor item in some_vec.iter() {\n some_vec.push(item.clone());\n}\nRun Code Online (Sandbox Code Playgroud)\nVec::push()需要可变地借用 Vec,但迭代需要不变地借用 Vec。你不能同时做这两件事。
Rust 不允许你做这些事情,因为它们从根本上来说是不健全的操作。Rust 语言的全部目的是在编译时准确捕获此类问题。
\n请注意,这在 C++ 中也是不安全的,例如,向 an 添加元素std::vector 可能会使所有现有引用无效(在重新分配的情况下),当您尝试使用无效引用时,这可能会导致未定义的行为。
不同的是C++会接受这个危险的代码。在 C++ 中,检查内存安全是程序员的工作,如果搞砸了,就会出现潜在的灾难性错误,甚至是严重的安全漏洞。
\n这就是 Rust 被创建的原因——承担人类不擅长的这项关键任务,并让编译器为你完成它。
\n