Rollup merge of #32815 - allonsy:master, r=GuillaumeGomez

Adds data race in docs

Thanks for all your hard work!
This is in reference to #32733
I know there has been a discussion about this on PR #32538 so you are welcome to keep the code as is or merge my documentation in.
Let me know what you think and/or if you want me to modify anything!
This commit is contained in:
Steve Klabnik 2016-04-11 10:31:27 -04:00
commit b5fc27cc81

View File

@ -162,7 +162,7 @@ The same [ownership system](ownership.html) that helps prevent using pointers
incorrectly also helps rule out data races, one of the worst kinds of incorrectly also helps rule out data races, one of the worst kinds of
concurrency bugs. concurrency bugs.
As an example, here is a Rust program that could have a data race in many As an example, here is a Rust program that would have a data race in many
languages. It will not compile: languages. It will not compile:
```ignore ```ignore
@ -174,7 +174,7 @@ fn main() {
for i in 0..3 { for i in 0..3 {
thread::spawn(move || { thread::spawn(move || {
data[i] += 1; data[0] += i;
}); });
} }
@ -186,7 +186,7 @@ This gives us an error:
```text ```text
8:17 error: capture of moved value: `data` 8:17 error: capture of moved value: `data`
data[i] += 1; data[0] += i;
^~~~ ^~~~
``` ```
@ -195,11 +195,6 @@ thread, and the thread takes ownership of the reference, we'd have three owners!
`data` gets moved out of `main` in the first call to `spawn()`, so subsequent `data` gets moved out of `main` in the first call to `spawn()`, so subsequent
calls in the loop cannot use this variable. calls in the loop cannot use this variable.
Note that this specific example will not cause a data race since different array
indices are being accessed. But this can't be determined at compile time, and in
a similar situation where `i` is a constant or is random, you would have a data
race.
So, we need some type that lets us have more than one owning reference to a So, we need some type that lets us have more than one owning reference to a
value. Usually, we'd use `Rc<T>` for this, which is a reference counted type value. Usually, we'd use `Rc<T>` for this, which is a reference counted type
that provides shared ownership. It has some runtime bookkeeping that keeps track that provides shared ownership. It has some runtime bookkeeping that keeps track
@ -223,7 +218,7 @@ fn main() {
// use it in a thread // use it in a thread
thread::spawn(move || { thread::spawn(move || {
data_ref[i] += 1; data_ref[0] += i;
}); });
} }
@ -266,7 +261,7 @@ fn main() {
for i in 0..3 { for i in 0..3 {
let data = data.clone(); let data = data.clone();
thread::spawn(move || { thread::spawn(move || {
data[i] += 1; data[0] += i;
}); });
} }
@ -281,7 +276,7 @@ And... still gives us an error.
```text ```text
<anon>:11:24 error: cannot borrow immutable borrowed content as mutable <anon>:11:24 error: cannot borrow immutable borrowed content as mutable
<anon>:11 data[i] += 1; <anon>:11 data[0] += i;
^~~~ ^~~~
``` ```
@ -317,7 +312,7 @@ fn main() {
let data = data.clone(); let data = data.clone();
thread::spawn(move || { thread::spawn(move || {
let mut data = data.lock().unwrap(); let mut data = data.lock().unwrap();
data[i] += 1; data[0] += i;
}); });
} }
@ -360,7 +355,7 @@ Let's examine the body of the thread more closely:
# let data = data.clone(); # let data = data.clone();
thread::spawn(move || { thread::spawn(move || {
let mut data = data.lock().unwrap(); let mut data = data.lock().unwrap();
data[i] += 1; data[0] += i;
}); });
# } # }
# thread::sleep(Duration::from_millis(50)); # thread::sleep(Duration::from_millis(50));