@@ -6,26 +6,28 @@ Safe Rust guarantees an absence of data races, which are defined as:
6
6
* one or more of them is a write
7
7
* one or more of them is unsynchronized
8
8
9
- A data race has Undefined Behavior, and is therefore impossible to perform
10
- in Safe Rust. Data races are * mostly* prevented through Rust's ownership system:
9
+ A data race has Undefined Behavior, and is therefore impossible to perform in
10
+ Safe Rust. Data races are * mostly* prevented through Rust's ownership system:
11
11
it's impossible to alias a mutable reference, so it's impossible to perform a
12
12
data race. Interior mutability makes this more complicated, which is largely why
13
- we have the Send and Sync traits (see below ).
13
+ we have the Send and Sync traits (see the next section for more on this ).
14
14
15
15
** However Rust does not prevent general race conditions.**
16
16
17
- This is pretty fundamentally impossible, and probably honestly undesirable. Your
18
- hardware is racy, your OS is racy, the other programs on your computer are racy,
19
- and the world this all runs in is racy. Any system that could genuinely claim to
20
- prevent * all * race conditions would be pretty awful to use, if not just
21
- incorrect .
17
+ This is mathematically impossible in situations where you do not control the
18
+ scheduler, which is true for the normal OS environment. If you do control
19
+ preemption, it _ can be _ possible to prevent general races - this technique is
20
+ used by frameworks such as [ RTIC ] ( https://github.com/rtic-rs/rtic ) . However,
21
+ actually having control over scheduling is a very uncommon case .
22
22
23
- So it's perfectly "fine" for a Safe Rust program to get deadlocked or do
24
- something nonsensical with incorrect synchronization. Obviously such a program
25
- isn't very good, but Rust can only hold your hand so far. Still, a race
26
- condition can't violate memory safety in a Rust program on its own. Only in
27
- conjunction with some other unsafe code can a race condition actually violate
28
- memory safety. For instance:
23
+ For this reason, it is considered "safe" for Rust to get deadlocked or do
24
+ something nonsensical with incorrect synchronization: this is known as a general
25
+ race condition or resource race. Obviously such a program isn't very good, but
26
+ Rust of course cannot prevent all logic errors.
27
+
28
+ In any case, a race condition cannot violate memory safety in a Rust program on
29
+ its own. Only in conjunction with some other unsafe code can a race condition
30
+ actually violate memory safety. For instance, a correct program looks like this:
29
31
30
32
``` rust,no_run
31
33
use std::thread;
@@ -58,6 +60,9 @@ thread::spawn(move || {
58
60
println!("{}", data[idx.load(Ordering::SeqCst)]);
59
61
```
60
62
63
+ We can cause a data race if we instead do the bound check in advance, and then
64
+ unsafely access the data with an unchecked value:
65
+
61
66
``` rust,no_run
62
67
use std::thread;
63
68
use std::sync::atomic::{AtomicUsize, Ordering};
0 commit comments