-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathch16-01-threads.html
More file actions
565 lines (493 loc) · 37 KB
/
Copy pathch16-01-threads.html
File metadata and controls
565 lines (493 loc) · 37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Threads - Threads - The Rust Programming Language</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<base href="">
<link rel="stylesheet" href="book.css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
<link rel="shortcut icon" href="favicon.png">
<!-- Font Awesome -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme -->
<style>
.page-wrapper.has-warning > .nav-chapters {
/* add height for warning content & margin */
top: 120px;
}
p.warning {
background-color: rgb(242, 222, 222);
border-bottom-color: rgb(238, 211, 215);
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom-style: solid;
border-bottom-width: 0.666667px;
border-image-outset: 0 0 0 0;
border-image-repeat: stretch stretch;
border-image-slice: 100% 100% 100% 100%;
border-image-source: none;
border-image-width: 1 1 1 1;
border-left-color: rgb(238, 211, 215);
border-left-style: solid;
border-left-width: 0.666667px;
border-right-color: rgb(238, 211, 215);
border-right-style: solid;
border-right-width: 0.666667px;
border-top-color: rgb(238, 211, 215);
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-top-style: solid;
border-top-width: 0.666667px;
color: rgb(185, 74, 72);
margin-bottom: 0px;
margin-left: 0px;
margin-right: 0px;
margin-top: 30px;
padding-bottom: 8px;
padding-left: 14px;
padding-right: 35px;
padding-top: 8px;
}
p.warning strong {
color: rgb(185, 74, 72)
}
p.warning a {
color: rgb(0, 136, 204)
}
a .hljs {
color: #4183c4;
}
.rust .content a .hljs,
.coal .content a .hljs,
.navy .content a .hljs {
color: #2b79a2;
}
a:hover .hljs {
text-decoration: underline;
}
/* Styles keystrokes such as ctrl-C */
.keystroke {
font-variant: small-caps;
}
</style>
<!-- Fetch Clipboard.js from CDN but have a local fallback -->
<script src="https://cdn.jsdelivr.net/clipboard.js/1.6.1/clipboard.min.js"></script>
<script>
if (typeof Clipboard == 'undefined') {
document.write(unescape("%3Cscript src='clipboard.min.js'%3E%3C/script%3E"));
}
</script>
<!-- Fetch JQuery from CDN but have a local fallback -->
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script>
if (typeof jQuery == 'undefined') {
document.write(unescape("%3Cscript src='jquery.js'%3E%3C/script%3E"));
}
</script>
<!-- Fetch store.js from local - TODO add CDN when 2.x.x is available on cdnjs -->
<script src="store.js"></script>
<!-- Custom JS script -->
</head>
<body class="light">
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme = store.get('mdbook-theme');
if (theme === null || theme === undefined) { theme = 'light'; }
$('body').removeClass().addClass(theme);
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var sidebar = store.get('mdbook-sidebar');
if (sidebar === "hidden") { $("html").addClass("sidebar-hidden") }
else if (sidebar === "visible") { $("html").addClass("sidebar-visible") }
</script>
<div id="sidebar" class="sidebar">
<ul class="chapter"><li><a href="ch01-00-introduction.html"><strong>1.</strong> Introduction</a></li><li><ul class="section"><li><a href="ch01-01-installation.html"><strong>1.1.</strong> Installation</a></li><li><a href="ch01-02-hello-world.html"><strong>1.2.</strong> Hello, World!</a></li></ul></li><li><a href="ch02-00-guessing-game-tutorial.html"><strong>2.</strong> Guessing Game Tutorial</a></li><li><a href="ch03-00-common-programming-concepts.html"><strong>3.</strong> Common Programming Concepts</a></li><li><ul class="section"><li><a href="ch03-01-variables-and-mutability.html"><strong>3.1.</strong> Variables and Mutability</a></li><li><a href="ch03-02-data-types.html"><strong>3.2.</strong> Data Types</a></li><li><a href="ch03-03-how-functions-work.html"><strong>3.3.</strong> How Functions Work</a></li><li><a href="ch03-04-comments.html"><strong>3.4.</strong> Comments</a></li><li><a href="ch03-05-control-flow.html"><strong>3.5.</strong> Control Flow</a></li></ul></li><li><a href="ch04-00-understanding-ownership.html"><strong>4.</strong> Understanding Ownership</a></li><li><ul class="section"><li><a href="ch04-01-what-is-ownership.html"><strong>4.1.</strong> What is Ownership?</a></li><li><a href="ch04-02-references-and-borrowing.html"><strong>4.2.</strong> References & Borrowing</a></li><li><a href="ch04-03-slices.html"><strong>4.3.</strong> Slices</a></li></ul></li><li><a href="ch05-00-structs.html"><strong>5.</strong> Using Structs to Structure Related Data</a></li><li><ul class="section"><li><a href="ch05-01-defining-structs.html"><strong>5.1.</strong> Defining and Instantiating Structs</a></li><li><a href="ch05-02-example-structs.html"><strong>5.2.</strong> An Example Program Using Structs</a></li><li><a href="ch05-03-method-syntax.html"><strong>5.3.</strong> Method Syntax</a></li></ul></li><li><a href="ch06-00-enums.html"><strong>6.</strong> Enums and Pattern Matching</a></li><li><ul class="section"><li><a href="ch06-01-defining-an-enum.html"><strong>6.1.</strong> Defining an Enum</a></li><li><a href="ch06-02-match.html"><strong>6.2.</strong> The <code>match</code> Control Flow Operator</a></li><li><a href="ch06-03-if-let.html"><strong>6.3.</strong> Concise Control Flow with <code>if let</code></a></li></ul></li><li><a href="ch07-00-modules.html"><strong>7.</strong> Modules</a></li><li><ul class="section"><li><a href="ch07-01-mod-and-the-filesystem.html"><strong>7.1.</strong> <code>mod</code> and the Filesystem</a></li><li><a href="ch07-02-controlling-visibility-with-pub.html"><strong>7.2.</strong> Controlling Visibility with <code>pub</code></a></li><li><a href="ch07-03-importing-names-with-use.html"><strong>7.3.</strong> Referring to Names in Different Modules</a></li></ul></li><li><a href="ch08-00-common-collections.html"><strong>8.</strong> Common Collections</a></li><li><ul class="section"><li><a href="ch08-01-vectors.html"><strong>8.1.</strong> Vectors</a></li><li><a href="ch08-02-strings.html"><strong>8.2.</strong> Strings</a></li><li><a href="ch08-03-hash-maps.html"><strong>8.3.</strong> Hash Maps</a></li></ul></li><li><a href="ch09-00-error-handling.html"><strong>9.</strong> Error Handling</a></li><li><ul class="section"><li><a href="ch09-01-unrecoverable-errors-with-panic.html"><strong>9.1.</strong> Unrecoverable Errors with <code>panic!</code></a></li><li><a href="ch09-02-recoverable-errors-with-result.html"><strong>9.2.</strong> Recoverable Errors with <code>Result</code></a></li><li><a href="ch09-03-to-panic-or-not-to-panic.html"><strong>9.3.</strong> To <code>panic!</code> or Not To <code>panic!</code></a></li></ul></li><li><a href="ch10-00-generics.html"><strong>10.</strong> Generic Types, Traits, and Lifetimes</a></li><li><ul class="section"><li><a href="ch10-01-syntax.html"><strong>10.1.</strong> Generic Data Types</a></li><li><a href="ch10-02-traits.html"><strong>10.2.</strong> Traits: Defining Shared Behavior</a></li><li><a href="ch10-03-lifetime-syntax.html"><strong>10.3.</strong> Validating References with Lifetimes</a></li></ul></li><li><a href="ch11-00-testing.html"><strong>11.</strong> Testing</a></li><li><ul class="section"><li><a href="ch11-01-writing-tests.html"><strong>11.1.</strong> Writing tests</a></li><li><a href="ch11-02-running-tests.html"><strong>11.2.</strong> Running tests</a></li><li><a href="ch11-03-test-organization.html"><strong>11.3.</strong> Test Organization</a></li></ul></li><li><a href="ch12-00-an-io-project.html"><strong>12.</strong> An I/O Project: Building a Command Line Program</a></li><li><ul class="section"><li><a href="ch12-01-accepting-command-line-arguments.html"><strong>12.1.</strong> Accepting Command Line Arguments</a></li><li><a href="ch12-02-reading-a-file.html"><strong>12.2.</strong> Reading a File</a></li><li><a href="ch12-03-improving-error-handling-and-modularity.html"><strong>12.3.</strong> Refactoring to Improve Modularity and Error Handling</a></li><li><a href="ch12-04-testing-the-librarys-functionality.html"><strong>12.4.</strong> Developing the Library’s Functionality with Test Driven Development</a></li><li><a href="ch12-05-working-with-environment-variables.html"><strong>12.5.</strong> Working with Environment Variables</a></li><li><a href="ch12-06-writing-to-stderr-instead-of-stdout.html"><strong>12.6.</strong> Writing Error Messages to Standard Error Instead of Standard Output</a></li></ul></li><li><a href="ch13-00-functional-features.html"><strong>13.</strong> Functional Language Features: Iterators and Closures</a></li><li><ul class="section"><li><a href="ch13-01-closures.html"><strong>13.1.</strong> Closures: Anonymous Functions that Can Capture Their Environment</a></li><li><a href="ch13-02-iterators.html"><strong>13.2.</strong> Processing a Series of Items with Iterators</a></li><li><a href="ch13-03-improving-our-io-project.html"><strong>13.3.</strong> Improving Our I/O Project</a></li><li><a href="ch13-04-performance.html"><strong>13.4.</strong> Comparing Performance: Loops vs. Iterators</a></li></ul></li><li><a href="ch14-00-more-about-cargo.html"><strong>14.</strong> More about Cargo and Crates.io</a></li><li><ul class="section"><li><a href="ch14-01-release-profiles.html"><strong>14.1.</strong> Customizing Builds with Release Profiles</a></li><li><a href="ch14-02-publishing-to-crates-io.html"><strong>14.2.</strong> Publishing a Crate to Crates.io</a></li><li><a href="ch14-03-cargo-workspaces.html"><strong>14.3.</strong> Cargo Workspaces</a></li><li><a href="ch14-04-installing-binaries.html"><strong>14.4.</strong> Installing Binaries from Crates.io with <code>cargo install</code></a></li><li><a href="ch14-05-extending-cargo.html"><strong>14.5.</strong> Extending Cargo with Custom Commands</a></li></ul></li><li><a href="ch15-00-smart-pointers.html"><strong>15.</strong> Smart Pointers</a></li><li><ul class="section"><li><a href="ch15-01-box.html"><strong>15.1.</strong> <code>Box<T></code> Points to Data on the Heap and Has a Known Size</a></li><li><a href="ch15-02-deref.html"><strong>15.2.</strong> The <code>Deref</code> Trait Allows Access to the Data Through a Reference</a></li><li><a href="ch15-03-drop.html"><strong>15.3.</strong> The <code>Drop</code> Trait Runs Code on Cleanup</a></li><li><a href="ch15-04-rc.html"><strong>15.4.</strong> <code>Rc<T></code>, the Reference Counted Smart Pointer</a></li><li><a href="ch15-05-interior-mutability.html"><strong>15.5.</strong> <code>RefCell<T></code> and the Interior Mutability Pattern</a></li><li><a href="ch15-06-reference-cycles.html"><strong>15.6.</strong> Creating Reference Cycles and Leaking Memory is Safe</a></li></ul></li><li><a href="ch16-00-concurrency.html"><strong>16.</strong> Fearless Concurrency</a></li><li><ul class="section"><li><a href="ch16-01-threads.html" class="active"><strong>16.1.</strong> Threads</a></li><li><a href="ch16-02-message-passing.html"><strong>16.2.</strong> Message Passing</a></li><li><a href="ch16-03-shared-state.html"><strong>16.3.</strong> Shared State</a></li><li><a href="ch16-04-extensible-concurrency-sync-and-send.html"><strong>16.4.</strong> Extensible Concurrency: <code>Sync</code> and <code>Send</code></a></li></ul></li><li><a href="ch17-00-oop.html"><strong>17.</strong> Is Rust an Object-Oriented Programming Language?</a></li><li><ul class="section"><li><a href="ch17-01-what-is-oo.html"><strong>17.1.</strong> What Does Object-Oriented Mean?</a></li><li><a href="ch17-02-trait-objects.html"><strong>17.2.</strong> Trait Objects for Using Values of Different Types</a></li><li><a href="ch17-03-oo-design-patterns.html"><strong>17.3.</strong> Object-Oriented Design Pattern Implementations</a></li></ul></li><li><a href="ch18-00-patterns.html"><strong>18.</strong> Patterns Match the Structure of Values</a></li><li><ul class="section"><li><a href="ch18-01-all-the-places-for-patterns.html"><strong>18.1.</strong> All the Places Patterns May be Used</a></li><li><a href="ch18-02-refutability.html"><strong>18.2.</strong> Refutability: Whether a Pattern Might Fail to Match</a></li><li><a href="ch18-03-pattern-syntax.html"><strong>18.3.</strong> All the Pattern Syntax</a></li></ul></li><li><a href="ch19-00-advanced-features.html"><strong>19.</strong> Advanced Features</a></li><li><ul class="section"><li><a href="ch19-01-unsafe-rust.html"><strong>19.1.</strong> Unsafe Rust</a></li><li><a href="ch19-02-advanced-lifetimes.html"><strong>19.2.</strong> Advanced Lifetimes</a></li><li><a href="ch19-03-advanced-traits.html"><strong>19.3.</strong> Advanced Traits</a></li><li><a href="ch19-04-advanced-types.html"><strong>19.4.</strong> Advanced Types</a></li><li><a href="ch19-05-advanced-functions-and-closures.html"><strong>19.5.</strong> Advanced Functions & Closures</a></li></ul></li><li><a href="ch20-00-final-project-a-web-server.html"><strong>20.</strong> Final Project: Building a Multithreaded Web Server</a></li><li><ul class="section"><li><a href="ch20-01-single-threaded.html"><strong>20.1.</strong> A Single Threaded Web Server</a></li><li><a href="ch20-02-slow-requests.html"><strong>20.2.</strong> How Slow Requests Affect Throughput</a></li><li><a href="ch20-03-designing-the-interface.html"><strong>20.3.</strong> Designing the Thread Pool Interface</a></li><li><a href="ch20-04-storing-threads.html"><strong>20.4.</strong> Creating the Thread Pool and Storing Threads</a></li><li><a href="ch20-05-sending-requests-via-channels.html"><strong>20.5.</strong> Sending Requests to Threads Via Channels</a></li><li><a href="ch20-06-graceful-shutdown-and-cleanup.html"><strong>20.6.</strong> Graceful Shutdown and Cleanup</a></li></ul></li><li><a href="appendix-00.html"><strong>21.</strong> Appendix</a></li><li><ul class="section"><li><a href="appendix-01-keywords.html"><strong>21.1.</strong> A - Keywords</a></li><li><a href="appendix-02-operators.html"><strong>21.2.</strong> B - Operators and Symbols</a></li><li><a href="appendix-03-derivable-traits.html"><strong>21.3.</strong> C - Derivable Traits</a></li><li><a href="appendix-04-macros.html"><strong>21.4.</strong> D - Macros</a></li><li><a href="appendix-05-translation.html"><strong>21.5.</strong> E - Translations</a></li><li><a href="appendix-06-newest-features.html"><strong>21.6.</strong> F - Newest Features</a></li></ul></li></ul>
</div>
<div id="page-wrapper" class="page-wrapper has-warning">
<div class="page" tabindex="-1">
<header><p class="warning">You are reading a <strong>draft</strong> of the next edition of TRPL. For more, go <a href="../index.html">here</a>.</p></header>
<div id="menu-bar" class="menu-bar">
<div class="left-buttons">
<i id="sidebar-toggle" class="fa fa-bars"></i>
<i id="theme-toggle" class="fa fa-paint-brush"></i>
</div>
<h1 class="menu-title">The Rust Programming Language</h1>
<div class="right-buttons">
<a href="print.html">
<i id="print-button" class="fa fa-print" title="Print this book"></i>
</a>
</div>
</div>
<div id="content" class="content">
<a class="header" href="ch16-01-threads.html#using-threads-to-run-code-simultaneously" id="using-threads-to-run-code-simultaneously"><h2>Using Threads to Run Code Simultaneously</h2></a>
<p>In most operating systems today, an executed program’s code is run in a
<em>process</em>, and the operating system manages multiple process at once. Within
your program, you can also have independent parts that run simultaneously. The
feature that runs these independent parts is called <em>threads</em>.</p>
<!-- I've tried to simplify the text above, can you check that I haven't
changed meaning? -->
<!-- Made some small tweaks, overall seems fine /Carol -->
<p>Splitting the computation in your program up into multiple threads can improve
performance, since the program will be doing multiple things at the same time,
but it also adds complexity. Because threads may run simultaneously, there’s no
inherent guarantee about the order in which parts of your code on different
threads will run. This can lead to problems such as:</p>
<ul>
<li>Race conditions, where threads are accessing data or resources in an
inconsistent order</li>
<li>Deadlocks, where two threads are waiting for each other to finish using a
resource the other thread has, which prevents both threads from continuing</li>
<li>Bugs that only happen in certain situations and are hard to reproduce and
fix reliably</li>
</ul>
<!-- How do threads prevent each other from continuing? Or is that something
we'll cover later?-->
<!-- We don't really get into that later, so I've expanded a bit here /Carol -->
<p>Rust attempts to mitigate negative effects of using threads. Programming in a
multithreaded context still takes careful thought and requires a code structure
that’s different from programs that run in a single thread.</p>
<p>Programming languages implement threads in a few different ways. Many operating
systems provide an API for creating new threads. This model where a language
calls the operating system APIs to create threads is sometimes called <em>1:1</em>,
one OS thread per one language thread.</p>
<p>Many programming languages provide their own special implementation of threads.
Programming language-provided threads are known as <em>green</em> threads, and
languages that use these green threads will execute them in the context of a
different number of operating system threads. For this reason, the green
threaded model is called the <em>M:N</em> model, <code>M</code> green threads per <code>N</code> OS threads,
where <code>M</code> and <code>N</code> are not necessarily the same number.</p>
<p>Each model has its own advantages and tradeoffs, and the tradeoff most
important to Rust is runtime support. <em>Runtime</em> is a confusing term and can
have different meanings in different contexts.</p>
<!-- Below - you mean this is the cause of runtime? Or "runtime" literally
means the code included by Rust in every binary? -->
<!-- Runtime literally means the code included by Rust in every binary.
Wikipedia calls this "runtime system":
https://en.wikipedia.org/wiki/Runtime_system but most people colloquially just
say "the runtime". I've tried to clarify. /Carol -->
<p>In this context, by runtime we mean code that’s included by the language in
every binary. This code can be large or small depending on the language, but
every non-assembly language will have some amount of runtime code. For that
reason, colloquially when people say a language has “no runtime” they often
mean “small runtime.” Smaller runtimes have fewer features but have the
advantage of resulting in smaller binaries, which make it easier to combine the
language with other languages in more contexts. While many languages are okay
with increasing the runtime size in exchange for more features, Rust needs to
have nearly no runtime, and cannot compromise on being able to call into C in
order to maintain performance.</p>
<p>The green threading M:N model requires a larger language runtime to manage
threads. As such, the Rust standard library only provides an implementation of
1:1 threading. Because Rust is such a low-level language, there are crates that
implement M:N threading if you would rather trade overhead for aspects such as
more control over which threads run when and lower costs of context switching,
for example.</p>
<p>Now that we’ve defined threads in Rust, let’s explore how to use the
thread-related API provided by the standard library.</p>
<a class="header" href="ch16-01-threads.html#creating-a-new-thread-with-spawn" id="creating-a-new-thread-with-spawn"><h3>Creating a New Thread with <code>spawn</code></h3></a>
<p>To create a new thread, we call the <code>thread::spawn</code> function, and pass it a
closure (we talked about closures in Chapter 13) containing the code we want to
run in the new thread. The example in Listing 16-1 prints some text from a main
thread and other text from a new thread:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">use std::thread;
use std::time::Duration;
fn main() {
thread::spawn(|| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("hi number {} from the main thread!", i);
thread::sleep(Duration::from_millis(1));
}
}
</code></pre></pre>
<p><span class="caption">Listing 16-1: Creating a new thread to print one thing
while the main thread prints something else</span></p>
<p>Note that with this function, the new thread will be stopped when the main
thread ends, whether it has finished running or not. The output from this
program might be a little different every time, but it will look similar to
this:</p>
<pre><code class="language-text">hi number 1 from the main thread!
hi number 1 from the spawned thread!
hi number 2 from the main thread!
hi number 2 from the spawned thread!
hi number 3 from the main thread!
hi number 3 from the spawned thread!
hi number 4 from the main thread!
hi number 4 from the spawned thread!
hi number 5 from the spawned thread!
</code></pre>
<!-- This seems interesting, how come the threads often take turns, but not
always? -->
<!-- I've added a bit of clarification /Carol -->
<p>The <code>thread::sleep</code> function will force a thread to stop its execution for a
short duration, allowing a different thread to run, so that they will probably
take turns, but that’s not guaranteed: it depends on how your operating system
schedules the threads. In this run, the main thread printed first, even though
the print statement from the spawned thread appears first in the code. And even
though we told the spawned thread to print until <code>i</code> is 9, it only got to 5
before the main thread shut down.</p>
<p>If you run this code and only see one thread, or don’t see any overlap, try
increasing the numbers in the ranges to create more opportunities for a thread
to take a break and give the other thread a turn.</p>
<a class="header" href="ch16-01-threads.html#waiting-for-all-threads-to-finish-using-join-handles" id="waiting-for-all-threads-to-finish-using-join-handles"><h4>Waiting for All Threads to Finish Using <code>join</code> Handles</h4></a>
<p>The code in Listing 16-1 not only stops the spawned thread prematurely most of
the time, because the main thread ends before the spawned thread is done,
there’s actually no guarantee that the spawned thread will get to run at all,
because there’s no guarantee on the order in which threads run!</p>
<!-- Above -- why is this the case, because there are no guarantees over which
order the threads run in? -->
<!-- Yep! /Carol -->
<p>We can fix this by saving the return value of <code>thread::spawn</code> in a variable.
The return type of <code>thread::spawn</code> is <code>JoinHandle</code>. A <code>JoinHandle</code> is an owned
value that, when we call the <code>join</code> method on it, will wait for its thread to
finish. Listing 16-2 shows how to use the <code>JoinHandle</code> of the thread we created
in Listing 16-1 and call <code>join</code> in order to make sure the spawned thread
finishes before the <code>main</code> exits:</p>
<!-- Saving the return value where? I think this explanation of join handle
needs expanding, this feels cut short -->
<!-- In a variable. I've expanded a bit, but I'm not sure what information
seems missing, so I'm not sure if this is sufficient /Carol -->
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">use std::thread;
use std::time::Duration;
fn main() {
let handle = thread::spawn(|| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("hi number {} from the main thread!", i);
thread::sleep(Duration::from_millis(1));
}
handle.join();
}
</code></pre></pre>
<p><span class="caption">Listing 16-2: Saving a <code>JoinHandle</code> from <code>thread::spawn</code>
to guarantee the thread is run to completion</span></p>
<p>Calling <code>join</code> on the handle blocks the thread currently running until the
thread represented by the handle terminates. <em>Blocking</em> a thread means that
thread is prevented from performing work or exiting. Because we’ve put the call
to <code>join</code> after the main thread’s <code>for</code> loop, running this example should
produce output that looks something like this:</p>
<!-- Liz: I've added a definition of "block" in the context of threads here,
which is the first time we used the term-- it seemed to cause some confusion
later on. /Carol -->
<pre><code class="language-text">hi number 1 from the main thread!
hi number 2 from the main thread!
hi number 1 from the spawned thread!
hi number 3 from the main thread!
hi number 2 from the spawned thread!
hi number 4 from the main thread!
hi number 3 from the spawned thread!
hi number 4 from the spawned thread!
hi number 5 from the spawned thread!
hi number 6 from the spawned thread!
hi number 7 from the spawned thread!
hi number 8 from the spawned thread!
hi number 9 from the spawned thread!
</code></pre>
<p>The two threads are still alternating, but the main thread waits because of the
call to <code>handle.join()</code> and does not end until the spawned thread is finished.</p>
<p>If we instead move <code>handle.join()</code> before the <code>for</code> loop in main, like this:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">use std::thread;
use std::time::Duration;
fn main() {
let handle = thread::spawn(|| {
for i in 1..10 {
println!("hi number {} from the spawned thread!", i);
thread::sleep(Duration::from_millis(1));
}
});
handle.join();
for i in 1..5 {
println!("hi number {} from the main thread!", i);
thread::sleep(Duration::from_millis(1));
}
}
</code></pre></pre>
<p>The main thread will wait for the spawned thread to finish and then run its
<code>for</code> loop, so the output won’t be interleaved anymore:</p>
<pre><code class="language-text">hi number 1 from the spawned thread!
hi number 2 from the spawned thread!
hi number 3 from the spawned thread!
hi number 4 from the spawned thread!
hi number 5 from the spawned thread!
hi number 6 from the spawned thread!
hi number 7 from the spawned thread!
hi number 8 from the spawned thread!
hi number 9 from the spawned thread!
hi number 1 from the main thread!
hi number 2 from the main thread!
hi number 3 from the main thread!
hi number 4 from the main thread!
</code></pre>
<p>Thinking about a small thing such as where to call <code>join</code> can affect whether
your threads are actually running at the same time or not.</p>
<a class="header" href="ch16-01-threads.html#using-move-closures-with-threads" id="using-move-closures-with-threads"><h3>Using <code>move</code> Closures with Threads</h3></a>
<p>The <code>move</code> closure, which we didn’t cover in Chapter 13, is often used
alongside <code>thread::spawn</code>, as it allows us to use data from one thread in
another thread.</p>
<p>In Chapter 13, we said that “Creating closures that capture values from their
environment is mostly used in the context of starting new threads.”</p>
<!-- PROD: DE to check this quote, see if it has changed -->
<p>Now we’re creating new threads, so let’s talk about capturing values in
closures!</p>
<p>Notice in Listing 16-1 that the closure we pass to <code>thread::spawn</code> takes no
arguments: we’re not using any data from the main thread in the spawned
thread’s code. In order to do so, the spawned thread’s closure must capture the
values it needs. Listing 16-3 shows an attempt to create a vector in the main
thread and use it in the spawned thread. However, this won’t yet work, as
you’ll see in a moment:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust ignore">use std::thread;
fn main() {
let v = vec![1, 2, 3];
let handle = thread::spawn(|| {
println!("Here's a vector: {:?}", v);
});
handle.join();
}
</code></pre>
<p><span class="caption">Listing 16-3: Attempting to use a vector created by the
main thread in another thread</span></p>
<p>The closure uses <code>v</code>, so will capture <code>v</code> and make it part of the closure’s
environment. Because <code>thread::spawn</code> runs this closure in a new thread, we
should be able to access <code>v</code> inside that new thread.</p>
<p>When we compile this example, however, we’ll get the following error:</p>
<pre><code class="language-text">error[E0373]: closure may outlive the current function, but it borrows `v`,
which is owned by the current function
-->
|
6 | let handle = thread::spawn(|| {
| ^^ may outlive borrowed value `v`
7 | println!("Here's a vector: {:?}", v);
| - `v` is borrowed here
|
help: to force the closure to take ownership of `v` (and any other referenced
variables), use the `move` keyword, as shown:
| let handle = thread::spawn(move || {
</code></pre>
<p>Rust <em>infers</em> how to capture <code>v</code>, and since <code>println!</code> only needs a reference
to <code>v</code>, the closure tries to borrow <code>v</code>. There’s a problem, though: Rust can’t
tell how long the spawned thread will run, so doesn’t know if the reference to
<code>v</code> will always be valid.</p>
<p>Let’s look at a scenario that’s more likely to have a reference to <code>v</code> that
won’t be valid, shown Listing 16-4:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust ignore">use std::thread;
fn main() {
let v = vec![1, 2, 3];
let handle = thread::spawn(|| {
println!("Here's a vector: {:?}", v);
});
drop(v); // oh no!
handle.join();
}
</code></pre>
<p><span class="caption">Listing 16-4: A thread with a closure that attempts to
capture a reference to <code>v</code> from a main thread that drops <code>v</code></span></p>
<p>If we run this code, there’s a possibility the spawned thread will be
immediately put in the background without getting a chance to run at all. The
spawned thread has a reference to <code>v</code> inside, but the main thread immediately
drops <code>v</code>, using the <code>drop</code> function we discussed in Chapter 15. Then, when the
spawned thread starts to execute, <code>v</code> is no longer valid, so a reference to it
is also invalid. Oh no!</p>
<p>To fix the problem in Listing 16-3, we can listen to the advice of the error
message:</p>
<pre><code class="language-text">help: to force the closure to take ownership of `v` (and any other referenced
variables), use the `move` keyword, as shown:
| let handle = thread::spawn(move || {
</code></pre>
<p>By adding the <code>move</code> keyword before the closure, we force the closure to take
ownership of the values it’s using, rather than allowing Rust to infer that it
should borrow. The modification to Listing 16-3 shown in Listing 16-5 will
compile and run as we intend:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">use std::thread;
fn main() {
let v = vec![1, 2, 3];
let handle = thread::spawn(move || {
println!("Here's a vector: {:?}", v);
});
handle.join();
}
</code></pre></pre>
<p><span class="caption">Listing 16-5: Using the <code>move</code> keyword to force a closure
to take ownership of the values it uses</span></p>
<!-- Can you be more specific about the question we're asking about 16-4?-->
<!-- Done /Carol -->
<p>What would happen to the code in Listing 16-4 where the main thread called
<code>drop</code> if we use a <code>move</code> closure? Would <code>move</code> fix that case? Nope, we get a
different error, because what Listing 16-4 is trying to do isn’t allowed for a
different reason! If we add <code>move</code> to the closure, we’d move <code>v</code> into the
closure’s environment, and we could no longer call <code>drop</code> on it in the main
thread. We would get this compiler error instead:</p>
<pre><code class="language-text">error[E0382]: use of moved value: `v`
-->
|
6 | let handle = thread::spawn(move || {
| ------- value moved (into closure) here
...
10 | drop(v); // oh no!
| ^ value used here after move
|
= note: move occurs because `v` has type `std::vec::Vec<i32>`, which does
not implement the `Copy` trait
</code></pre>
<p>Rust’s ownership rules have saved us again! We got an error from the code in
Listing 16-3 because Rust was being conservative and only borrowing <code>v</code> for the
thread, which meant the main thread could theoretically invalidate the spawned
thread’s reference. By telling Rust to move ownership of <code>v</code> to the spawned
thread, we’re guaranteeing to Rust that the main thread won’t use <code>v</code> anymore.
If we change Listing 16-4 in the same way, we’re then violating the ownership
rules when we try to use <code>v</code> in the main thread. The <code>move</code> keyword overrides
Rust’s conservative default of borrowing; it doesn’t let us violate the
ownership rules.</p>
<!-- Uh oh, I'm lost again, I thought we were trying to fix 16-4 with move, but
we don't want it to work, is that right? Can you talk about this a little?-->
<!-- I've tried to clarify a bit in the paragraph before this error and a bit
after the error /Carol -->
<p>Now that we have a basic understanding of threads and the thread API, let’s
talk about what we can actually <em>do</em> with threads.</p>
</div>
<!-- Mobile navigation buttons -->
<a rel="prev" href="ch16-00-concurrency.html" class="mobile-nav-chapters previous">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="ch16-02-message-passing.html" class="mobile-nav-chapters next">
<i class="fa fa-angle-right"></i>
</a>
</div>
<a href="ch16-00-concurrency.html" class="nav-chapters previous" title="You can navigate through the chapters using the arrow keys">
<i class="fa fa-angle-left"></i>
</a>
<a href="ch16-02-message-passing.html" class="nav-chapters next" title="You can navigate through the chapters using the arrow keys">
<i class="fa fa-angle-right"></i>
</a>
</div>
<!-- Local fallback for Font Awesome -->
<script>
if ($(".fa").css("font-family") !== "FontAwesome") {
$('<link rel="stylesheet" type="text/css" href="_FontAwesome/css/font-awesome.css">').prependTo('head');
}
</script>
<!-- Livereload script (if served using the cli tool) -->
<script src="highlight.js"></script>
<script src="book.js"></script>
</body>
</html>