“数据竞争无法通过编译”是 Rust 的招牌。这篇用能编译失败的真实例子逐条验证,再用 unsafe 故意造一个数据竞争看后果,最后说明它没有解决的另一类问题:逻辑上的竞态条件。
源码:
1 | use std::thread;
2 | fn main() {
3 | let mut counter = 0;
4 | thread::scope(|s| {
5 | s.spawn(|| { counter += 1; });
6 | s.spawn(|| { counter += 1; });
7 | });
8 | println!("{}", counter);
9 | }
编译:失败
error[E0499]: cannot borrow `counter` as mutable more than once at a time
--> <实验目录>/src/u94a.rs:6:17
|
4 | thread::scope(|s| {
| - has type `&'1 Scope<'1, '_>`
5 | s.spawn(|| { counter += 1; });
| -----------------------------
| | | |
| | | first borrow occurs due to use of `counter` in closure
| | first mutable borrow occurs here
| argument requires that `counter` is borrowed for `'1`
6 | s.spawn(|| { counter += 1; });
| ^^ ------- second borrow occurs due to use of `counter` in closure
| |
| second mutable borrow occurs here
|
note: requirement that the value outlives `'1` introduced here
--> <rust 标准库源码>/library/std/src/thread/scoped.rs:203:35
|
203 | F: FnOnce() -> T + Send + 'scope,
| ^^^^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0499`. 源码:
1 | use std::thread;
2 | fn main() {
3 | let mut v = vec![1, 2, 3];
4 | thread::scope(|s| {
5 | s.spawn(|| { println!("{:?}", v); });
6 | s.spawn(|| { v.push(4); });
7 | });
8 | }
编译:失败
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
--> <实验目录>/src/u94b.rs:6:17
|
4 | thread::scope(|s| {
| - has type `&'1 Scope<'1, '_>`
5 | s.spawn(|| { println!("{:?}", v); });
| ------------------------------------
| | | |
| | | first borrow occurs due to use of `v` in closure
| | immutable borrow occurs here
| argument requires that `v` is borrowed for `'1`
6 | s.spawn(|| { v.push(4); });
| ^^ - second borrow occurs due to use of `v` in closure
| |
| mutable borrow occurs here
|
note: requirement that the value outlives `'1` introduced here
--> <rust 标准库源码>/library/std/src/thread/scoped.rs:203:35
|
203 | F: FnOnce() -> T + Send + 'scope,
| ^^^^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0502`. 编译:成功
运行(退出码 0):
多个线程同时只读 &v:合计 21
每个线程一个不重叠的 &mut 切片:[1, 1, 2, 2, 3, 3]Send 与 Sync 的规则见Send 与 Sync。
源码:
1 | static mut COUNTER: u32 = 0;
2 | fn main() { unsafe { COUNTER += 1; let r = &COUNTER; println!("{}", r); } }
编译:失败
error: creating a shared reference to mutable static
--> <实验目录>/src/u94d.rs:2:44
|
2 | fn main() { unsafe { COUNTER += 1; let r = &COUNTER; println!("{}", r); } }
| ^^^^^^^^ shared reference to mutable static
|
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: `#[deny(static_mut_refs)]` (part of `#[deny(rust_2024_compatibility)]`) on by default
help: use `&raw const` instead to create a raw pointer
|
2 | fn main() { unsafe { COUNTER += 1; let r = &raw const COUNTER; println!("{}", r); } }
| +++++++++
error: aborting due to 1 previous error 源码:
1 | use std::{cell::UnsafeCell, thread};
2 | struct Racy(UnsafeCell<u64>);
3 | unsafe impl Sync for Racy {}
4 | fn main() {
5 | let c = Racy(UnsafeCell::new(0));
6 | thread::scope(|s| { s.spawn(|| { unsafe { *c.0.get() += 1; } }); });
7 | }
编译:失败
error[E0277]: `UnsafeCell<u64>` cannot be shared between threads safely
--> <实验目录>/src/u94e.rs:6:33
|
6 | thread::scope(|s| { s.spawn(|| { unsafe { *c.0.get() += 1; } }); });
| ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<u64>` cannot be shared between threads safely
| |
| required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `UnsafeCell<u64>`
= note: required for `&UnsafeCell<u64>` to implement `Send`
note: required because it's used within this closure
--> <实验目录>/src/u94e.rs:6:33
|
6 | thread::scope(|s| { s.spawn(|| { unsafe { *c.0.get() += 1; } }); });
| ^^
note: required by a bound in `Scope::<'scope, 'env>::spawn`
--> <rust 标准库源码>/library/std/src/thread/scoped.rs:203:28
|
201 | pub fn spawn<F, T>(&'scope self, f: F) -> ScopedJoinHandle<'scope, T>
| ----- required by a bound in this associated function
202 | where
203 | F: FnOnce() -> T + Send + 'scope,
| ^^^^ required by this bound in `Scope::<'scope, 'env>::spawn`
…(共 27 行) 编译:成功
运行(退出码 0):
期望 4000000,实际 999862(没有同步的并发写,更新丢失)这是未定义行为,结果只是这台机器、这次运行的现象。
编译:成功
运行(退出码 0):
库存只有 1 件,却卖出了 4 件;库存值 = -3原子类型与内存序见原子类型与内存序。