@@ -103,10 +103,9 @@ to change the inner `i32` to 6.
103103
104104Now, let’s try to share a value between multiple threads using ` Mutex<T> ` .
105105We’ll spin up 10 threads and have them each increment a counter value by 1, so
106- the counter goes from 0 to 10. Note that the next few examples will have
107- compiler errors, and we’ll use those errors to learn more about using
108- ` Mutex<T> ` and how Rust helps us use it correctly. Listing 16-13 has our
109- starting example:
106+ the counter goes from 0 to 10. The next example in Listing 16-13 will have
107+ a compiler error, and we’ll use that error to learn more about using
108+ ` Mutex<T> ` and how Rust helps us use it correctly.
110109
111110<span class =" filename " >Filename: src/main.rs</span >
112111
@@ -154,110 +153,23 @@ program.
154153We hinted that this example wouldn’t compile. Now let’s find out why!
155154
156155``` text
157- error[E0382]: capture of moved value: `counter`
158- --> src/main.rs:10:27
159- |
160- 9 | let handle = thread::spawn(move || {
161- | ------- value moved (into closure) here
162- 10 | let mut num = counter.lock().unwrap();
163- | ^^^^^^^ value captured here after move
164- |
165- = note: move occurs because `counter` has type `std::sync::Mutex<i32>`,
166- which does not implement the `Copy` trait
167-
168156error[E0382]: use of moved value: `counter`
169- --> src/main.rs:21:29
157+ --> src/main.rs:9:36
170158 |
1711599 | let handle = thread::spawn(move || {
172- | ------- value moved (into closure) here
173- ...
174- 21 | println!("Result: {}", *counter.lock().unwrap());
175- | ^^^^^^^ value used here after move
176- |
177- = note: move occurs because `counter` has type `std::sync::Mutex<i32>`,
178- which does not implement the `Copy` trait
179-
180- error: aborting due to 2 previous errors
181- ```
182-
183- The error message states that the ` counter ` value is moved into the closure and
184- then captured when we call ` lock ` . That description sounds like what we wanted,
185- but it’s not allowed!
186-
187- Let’s figure this out by simplifying the program. Instead of making 10 threads
188- in a ` for ` loop, let’s just make two threads without a loop and see what
189- happens. Replace the first ` for ` loop in Listing 16-13 with this code instead:
190-
191- ``` rust,ignore,does_not_compile
192- use std::sync::Mutex;
193- use std::thread;
194-
195- fn main() {
196- let counter = Mutex::new(0);
197- let mut handles = vec![];
198-
199- let handle = thread::spawn(move || {
200- let mut num = counter.lock().unwrap();
201-
202- *num += 1;
203- });
204- handles.push(handle);
205-
206- let handle2 = thread::spawn(move || {
207- let mut num2 = counter.lock().unwrap();
208-
209- *num2 += 1;
210- });
211- handles.push(handle2);
212-
213- for handle in handles {
214- handle.join().unwrap();
215- }
216-
217- println!("Result: {}", *counter.lock().unwrap());
218- }
219- ```
220-
221- We make two threads and change the variable names used with the second thread
222- to ` handle2 ` and ` num2 ` . When we run the code this time, compiling gives us the
223- following:
224-
225- ``` text
226- error[E0382]: capture of moved value: `counter`
227- --> src/main.rs:16:24
228- |
229- 8 | let handle = thread::spawn(move || {
230- | ------- value moved (into closure) here
231- ...
232- 16 | let mut num2 = counter.lock().unwrap();
233- | ^^^^^^^ value captured here after move
234- |
235- = note: move occurs because `counter` has type `std::sync::Mutex<i32>`,
236- which does not implement the `Copy` trait
237-
238- error[E0382]: use of moved value: `counter`
239- --> src/main.rs:26:29
240- |
241- 8 | let handle = thread::spawn(move || {
242- | ------- value moved (into closure) here
243- ...
244- 26 | println!("Result: {}", *counter.lock().unwrap());
245- | ^^^^^^^ value used here after move
160+ | ^^^^^^^ value moved into closure here,
161+ in previous iteration of loop
162+ 10 | let mut num = counter.lock().unwrap();
163+ | ------- use occurs due to use in closure
246164 |
247165 = note: move occurs because `counter` has type `std::sync::Mutex<i32>`,
248- which does not implement the `Copy` trait
249-
250- error: aborting due to 2 previous errors
166+ which does not implement the `Copy` trait
251167```
252168
253- Aha! The first error message indicates that ` counter ` is moved into the closure
254- for the thread associated with ` handle ` . That move is preventing us from
255- capturing ` counter ` when we try to call ` lock ` on it and store the result in
256- ` num2 ` in the second thread! So Rust is telling us that we can’t move ownership
257- of ` counter ` into multiple threads. This was hard to see earlier because our
258- threads were in a loop, and Rust can’t point to different threads in different
259- iterations of the loop. Let’s fix the compiler error with a multiple-ownership
260- method we discussed in Chapter 15.
169+ The error message states that the ` counter ` value was moved in the previous
170+ iteration of the loop. So Rust is telling us that we can’t move the ownership
171+ of lock ` counter ` into multiple threads. Let’s fix the compiler error with a
172+ multiple-ownership method we discussed in Chapter 15.
261173
262174#### Multiple Ownership with Multiple Threads
263175
@@ -304,30 +216,27 @@ Once again, we compile and get... different errors! The compiler is teaching us
304216a lot.
305217
306218``` text
307- error[E0277]: the trait bound `std::rc::Rc<std::sync::Mutex<i32>>:
308- std::marker::Send` is not satisfied in `[closure@src/main.rs:11:36:
309- 15:10 counter:std::rc::Rc<std::sync::Mutex<i32>>]`
219+ error[E0277]: `std::rc::Rc<std::sync::Mutex<i32>>` cannot be sent between threads safely
310220 --> src/main.rs:11:22
311221 |
31222211 | let handle = thread::spawn(move || {
313223 | ^^^^^^^^^^^^^ `std::rc::Rc<std::sync::Mutex<i32>>`
314224cannot be sent between threads safely
315225 |
316- = help: within `[closure@src/main.rs:11:36: 15 :10
317- counter:std::rc::Rc<std::sync::Mutex<i32>>]`, the trait `std::marker::Send` is
318- not implemented for `std::rc::Rc<std::sync::Mutex<i32>>`
226+ = help: within `[closure@src/main.rs:11:36: 14 :10
227+ counter:std::rc::Rc<std::sync::Mutex<i32>>]`, the trait `std::marker::Send`
228+ is not implemented for `std::rc::Rc<std::sync::Mutex<i32>>`
319229 = note: required because it appears within the type
320- `[closure@src/main.rs:11:36: 15 :10 counter:std::rc::Rc<std::sync::Mutex<i32>>]`
230+ `[closure@src/main.rs:11:36: 14 :10 counter:std::rc::Rc<std::sync::Mutex<i32>>]`
321231 = note: required by `std::thread::spawn`
322232```
323233
324- Wow, that error message is very wordy! Here are some important parts to focus
325- on: the first inline error says `` ` std::rc::Rc<std::sync::Mutex<i32>> ` cannot
326- be sent between threads safely ``. The reason for this is in the next important
327- part to focus on, the error message. The distilled error message says `` the
328- trait bound ` Send ` is not satisfied ``. We’ll talk about ` Send ` in the next
329- section: it’s one of the traits that ensures the types we use with threads are
330- meant for use in concurrent situations.
234+ Wow, that error message is very wordy! Here’s the important part to focus
235+ on: `` `Rc<Mutex<i32>>` cannot be sent between threads safely `` . The compiler
236+ is also telling us the reason why: ``the trait ` Send ` is not implemented for
237+ ` Rc<Mutex<i32>> ` ``. We’ll talk about ` Send ` in the next section: it’s one of
238+ the traits that ensures the types we use with threads are meant for use in
239+ concurrent situations.
331240
332241Unfortunately, ` Rc<T> ` is not safe to share across threads. When ` Rc<T> `
333242manages the reference count, it adds to the count for each call to ` clone ` and
0 commit comments