Auto merge of #23277 - aochagavia:intro, r=steveklabnik

cc @steveklabnik
This commit is contained in:
bors 2015-04-07 11:34:38 +00:00
commit b41f2df4ca

View file

@ -457,30 +457,25 @@ a problem. Thats what it means by cannot move out of captured outer
variable: our `thread::scoped` closure wants to take ownership, and it cant, variable: our `thread::scoped` closure wants to take ownership, and it cant,
because the closure for `map` wont let it. because the closure for `map` wont let it.
What to do here? Rust has two types that helps us: `Arc<T>` and `Mutex<T>`. What to do here? Rust has a type that helps us: `Mutex<T>`. Because the threads
*Arc* stands for "atomically reference counted". In other words, an Arc will are scoped, it is possible to use an _immutable_ reference to `numbers` inside
keep track of the number of references to something, and not free the of the closure. However, Rust prevents us from having multiple _mutable_
associated resource until the count is zero. The *atomic* portion refers to an references to the same object, so we need a `Mutex` to be able to modify what
Arc's usage of concurrency primitives to atomically update the count, making it we're sharing. A Mutex will synchronize our accesses, so that we can ensure
safe across threads. If we use an Arc, we can have our three references. But, that our mutation doesn't cause a data race.
an Arc does not allow mutable borrows of the data it holds, and we want to
modify what we're sharing. In this case, we can use a `Mutex<T>` inside of our
Arc. A Mutex will synchronize our accesses, so that we can ensure that our
mutation doesn't cause a data race.
Here's what using an Arc with a Mutex looks like: Here's what using a Mutex looks like:
```{rust} ```{rust}
use std::thread; use std::thread;
use std::sync::{Arc,Mutex}; use std::sync::Mutex;
fn main() { fn main() {
let numbers = Arc::new(Mutex::new(vec![1, 2, 3])); let numbers = &Mutex::new(vec![1, 2, 3]);
let guards: Vec<_> = (0..3).map(|i| { let guards: Vec<_> = (0..3).map(|i| {
let number = numbers.clone();
thread::scoped(move || { thread::scoped(move || {
let mut array = number.lock().unwrap(); let mut array = numbers.lock().unwrap();
array[i] += 1; array[i] += 1;
println!("numbers[{}] is {}", i, array[i]); println!("numbers[{}] is {}", i, array[i]);
}) })
@ -489,12 +484,9 @@ fn main() {
``` ```
We first have to `use` the appropriate library, and then we wrap our vector in We first have to `use` the appropriate library, and then we wrap our vector in
an Arc with the call to `Arc::new()`. Inside of the loop, we make a new a `Mutex` with the call to `Mutex::new()`. Inside of the loop, the `lock()`
reference to the Arc with the `clone()` method. This will increment the call will return us a reference to the value inside the Mutex, and block any
reference count. When each new `numbers` variable binding goes out of scope, it other calls to `lock()` until said reference goes out of scope.
will decrement the count. The `lock()` call will return us a reference to the
value inside the Mutex, and block any other calls to `lock()` until said
reference goes out of scope.
We can compile and run this program without error, and in fact, see the We can compile and run this program without error, and in fact, see the
non-deterministic aspect: non-deterministic aspect: