mirror of
https://github.com/Dhghomon/easy_rust
synced 2024-11-17 15:29:51 +00:00
420 lines
27 KiB
HTML
420 lines
27 KiB
HTML
<!DOCTYPE HTML>
|
|
<html lang="en" class="sidebar-visible no-js light">
|
|
<head>
|
|
<!-- Book generated using mdBook -->
|
|
<meta charset="UTF-8">
|
|
<title> Multiple threads - Easy Rust</title>
|
|
|
|
|
|
|
|
|
|
<!-- Custom HTML head -->
|
|
|
|
|
|
|
|
<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">
|
|
<meta name="theme-color" content="#ffffff" />
|
|
|
|
|
|
<link rel="icon" href="favicon.svg">
|
|
|
|
|
|
<link rel="shortcut icon" href="favicon.png">
|
|
|
|
<link rel="stylesheet" href="css/variables.css">
|
|
<link rel="stylesheet" href="css/general.css">
|
|
<link rel="stylesheet" href="css/chrome.css">
|
|
|
|
<link rel="stylesheet" href="css/print.css" media="print">
|
|
|
|
|
|
<!-- Fonts -->
|
|
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
|
|
|
|
<link rel="stylesheet" href="fonts/fonts.css">
|
|
|
|
|
|
<!-- Highlight.js Stylesheets -->
|
|
<link rel="stylesheet" href="highlight.css">
|
|
<link rel="stylesheet" href="tomorrow-night.css">
|
|
<link rel="stylesheet" href="ayu-highlight.css">
|
|
|
|
<!-- Custom theme stylesheets -->
|
|
|
|
|
|
|
|
</head>
|
|
<body>
|
|
<!-- Provide site root to javascript -->
|
|
<script type="text/javascript">
|
|
var path_to_root = "";
|
|
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
|
|
</script>
|
|
|
|
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
|
<script type="text/javascript">
|
|
try {
|
|
var theme = localStorage.getItem('mdbook-theme');
|
|
var sidebar = localStorage.getItem('mdbook-sidebar');
|
|
|
|
if (theme.startsWith('"') && theme.endsWith('"')) {
|
|
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
|
}
|
|
|
|
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
|
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
|
}
|
|
} catch (e) { }
|
|
</script>
|
|
|
|
<!-- Set the theme before any content is loaded, prevents flash -->
|
|
<script type="text/javascript">
|
|
var theme;
|
|
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
|
if (theme === null || theme === undefined) { theme = default_theme; }
|
|
var html = document.querySelector('html');
|
|
html.classList.remove('no-js')
|
|
html.classList.remove('light')
|
|
html.classList.add(theme);
|
|
html.classList.add('js');
|
|
</script>
|
|
|
|
<!-- Hide / unhide sidebar before it is displayed -->
|
|
<script type="text/javascript">
|
|
var html = document.querySelector('html');
|
|
var sidebar = 'hidden';
|
|
if (document.body.clientWidth >= 1080) {
|
|
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
|
sidebar = sidebar || 'visible';
|
|
}
|
|
html.classList.remove('sidebar-visible');
|
|
html.classList.add("sidebar-" + sidebar);
|
|
</script>
|
|
|
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
|
<div class="sidebar-scrollbox">
|
|
<ol class="chapter"><li class="chapter-item expanded "><a href="Chapter_0.html"><strong aria-hidden="true">1.</strong> Update</a></li><li class="chapter-item expanded "><a href="Chapter_1.html"><strong aria-hidden="true">2.</strong> Introduction</a></li><li class="chapter-item expanded "><a href="Chapter_2.html"><strong aria-hidden="true">3.</strong> Who am I?</a></li><li class="chapter-item expanded "><a href="Chapter_3.html"><strong aria-hidden="true">4.</strong> Writing Rust in Easy English</a></li><li class="chapter-item expanded "><a href="Chapter_4.html"><strong aria-hidden="true">5.</strong> Rust Playground</a></li><li class="chapter-item expanded "><a href="Chapter_5.html"><strong aria-hidden="true">6.</strong> 🚧 and ⚠️</a></li><li class="chapter-item expanded "><a href="Chapter_6.html"><strong aria-hidden="true">7.</strong> Comments</a></li><li class="chapter-item expanded "><a href="Chapter_7.html"><strong aria-hidden="true">8.</strong> Types</a></li><li class="chapter-item expanded "><a href="Chapter_8.html"><strong aria-hidden="true">9.</strong> Type inference</a></li><li class="chapter-item expanded "><a href="Chapter_9.html"><strong aria-hidden="true">10.</strong> Printing 'hello, world!'</a></li><li class="chapter-item expanded "><a href="Chapter_10.html"><strong aria-hidden="true">11.</strong> Display and debug</a></li><li class="chapter-item expanded "><a href="Chapter_11.html"><strong aria-hidden="true">12.</strong> Mutability (changing)</a></li><li class="chapter-item expanded "><a href="Chapter_12.html"><strong aria-hidden="true">13.</strong> The stack, the heap, and pointers</a></li><li class="chapter-item expanded "><a href="Chapter_13.html"><strong aria-hidden="true">14.</strong> More about printing</a></li><li class="chapter-item expanded "><a href="Chapter_14.html"><strong aria-hidden="true">15.</strong> Strings</a></li><li class="chapter-item expanded "><a href="Chapter_15.html"><strong aria-hidden="true">16.</strong> const and static</a></li><li class="chapter-item expanded "><a href="Chapter_16.html"><strong aria-hidden="true">17.</strong> More on references</a></li><li class="chapter-item expanded "><a href="Chapter_17.html"><strong aria-hidden="true">18.</strong> Mutable references</a></li><li class="chapter-item expanded "><a href="Chapter_18.html"><strong aria-hidden="true">19.</strong> Giving references to functions</a></li><li class="chapter-item expanded "><a href="Chapter_19.html"><strong aria-hidden="true">20.</strong> Copy types</a></li><li class="chapter-item expanded "><a href="Chapter_20.html"><strong aria-hidden="true">21.</strong> Collection types</a></li><li class="chapter-item expanded "><a href="Chapter_21.html"><strong aria-hidden="true">22.</strong> Vectors</a></li><li class="chapter-item expanded "><a href="Chapter_22.html"><strong aria-hidden="true">23.</strong> Tuples</a></li><li class="chapter-item expanded "><a href="Chapter_23.html"><strong aria-hidden="true">24.</strong> Control flow</a></li><li class="chapter-item expanded "><a href="Chapter_24.html"><strong aria-hidden="true">25.</strong> Structs</a></li><li class="chapter-item expanded "><a href="Chapter_25.html"><strong aria-hidden="true">26.</strong> Enums</a></li><li class="chapter-item expanded "><a href="Chapter_26.html"><strong aria-hidden="true">27.</strong> Loops</a></li><li class="chapter-item expanded "><a href="Chapter_27.html"><strong aria-hidden="true">28.</strong> Implementing structs and enums</a></li><li class="chapter-item expanded "><a href="Chapter_28.html"><strong aria-hidden="true">29.</strong> Destructuring</a></li><li class="chapter-item expanded "><a href="Chapter_29.html"><strong aria-hidden="true">30.</strong> References and the dot operator</a></li><li class="chapter-item expanded "><a href="Chapter_30.html"><strong aria-hidden="true">31.</strong> Generics</a></li><li class="chapter-item expanded "><a href="Chapter_31.html"><strong aria-hidden="true">32.</strong> Option and Result</a></li><li class="chapter-item expanded "><a href="Chapter_32.html"><strong aria-hidden="true">33.</strong> Other collections</a></li><li class="chapter-item expanded "><a href="Chapter_33.html"><strong aria-hidden="true">34.</strong> The ? operator</a></li><li class="chapter-item expanded "><a href="Chapter_34.html"><strong aria-hidden="true">35.</strong> Traits</a></li><li class="chapter-item expanded "><a href="Chapter_35.html"><strong aria-hidden="true">36.</strong> Chaining methods</a></li><li class="chapter-item expanded "><a href="Chapter_36.html"><strong aria-hidden="true">37.</strong> Iterators</a></li><li class="chapter-item expanded "><a href="Chapter_37.html"><strong aria-hidden="true">38.</strong> Closures</a></li><li class="chapter-item expanded "><a href="Chapter_38.html"><strong aria-hidden="true">39.</strong> The dbg! macro and .inspect</a></li><li class="chapter-item expanded "><a href="Chapter_39.html"><strong aria-hidden="true">40.</strong> Types of &str</a></li><li class="chapter-item expanded "><a href="Chapter_40.html"><strong aria-hidden="true">41.</strong> Lifetimes</a></li><li class="chapter-item expanded "><a href="Chapter_41.html"><strong aria-hidden="true">42.</strong> Interior mutability</a></li><li class="chapter-item expanded "><a href="Chapter_42.html"><strong aria-hidden="true">43.</strong> Cow</a></li><li class="chapter-item expanded "><a href="Chapter_43.html"><strong aria-hidden="true">44.</strong> Type aliases</a></li><li class="chapter-item expanded "><a href="Chapter_44.html"><strong aria-hidden="true">45.</strong> The todo! macro</a></li><li class="chapter-item expanded "><a href="Chapter_45.html"><strong aria-hidden="true">46.</strong> Rc</a></li><li class="chapter-item expanded "><a href="Chapter_46.html" class="active"><strong aria-hidden="true">47.</strong> Multiple threads</a></li><li class="chapter-item expanded "><a href="Chapter_47.html"><strong aria-hidden="true">48.</strong> Closures in functions</a></li><li class="chapter-item expanded "><a href="Chapter_48.html"><strong aria-hidden="true">49.</strong> impl Trait</a></li><li class="chapter-item expanded "><a href="Chapter_49.html"><strong aria-hidden="true">50.</strong> Arc</a></li><li class="chapter-item expanded "><a href="Chapter_50.html"><strong aria-hidden="true">51.</strong> Channels</a></li><li class="chapter-item expanded "><a href="Chapter_51.html"><strong aria-hidden="true">52.</strong> Reading Rust documentation</a></li><li class="chapter-item expanded "><a href="Chapter_52.html"><strong aria-hidden="true">53.</strong> Attributes</a></li><li class="chapter-item expanded "><a href="Chapter_53.html"><strong aria-hidden="true">54.</strong> Box</a></li><li class="chapter-item expanded "><a href="Chapter_54.html"><strong aria-hidden="true">55.</strong> Box around traits</a></li><li class="chapter-item expanded "><a href="Chapter_55.html"><strong aria-hidden="true">56.</strong> Default and the builder pattern</a></li><li class="chapter-item expanded "><a href="Chapter_56.html"><strong aria-hidden="true">57.</strong> Deref and DerefMut</a></li><li class="chapter-item expanded "><a href="Chapter_57.html"><strong aria-hidden="true">58.</strong> Crates and modules</a></li><li class="chapter-item expanded "><a href="Chapter_58.html"><strong aria-hidden="true">59.</strong> Testing</a></li><li class="chapter-item expanded "><a href="Chapter_59.html"><strong aria-hidden="true">60.</strong> External crates</a></li><li class="chapter-item expanded "><a href="Chapter_60.html"><strong aria-hidden="true">61.</strong> A tour of the standard library</a></li><li class="chapter-item expanded "><a href="Chapter_61.html"><strong aria-hidden="true">62.</strong> Writing macros</a></li><li class="chapter-item expanded "><a href="Chapter_62.html"><strong aria-hidden="true">63.</strong> cargo</a></li><li class="chapter-item expanded "><a href="Chapter_63.html"><strong aria-hidden="true">64.</strong> Taking user input</a></li><li class="chapter-item expanded "><a href="Chapter_64.html"><strong aria-hidden="true">65.</strong> Using files</a></li><li class="chapter-item expanded "><a href="Chapter_65.html"><strong aria-hidden="true">66.</strong> cargo doc</a></li><li class="chapter-item expanded "><a href="Chapter_66.html"><strong aria-hidden="true">67.</strong> The end?</a></li></ol>
|
|
</div>
|
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
|
</nav>
|
|
|
|
<div id="page-wrapper" class="page-wrapper">
|
|
|
|
<div class="page">
|
|
|
|
<div id="menu-bar-hover-placeholder"></div>
|
|
<div id="menu-bar" class="menu-bar sticky bordered">
|
|
<div class="left-buttons">
|
|
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
|
<i class="fa fa-bars"></i>
|
|
</button>
|
|
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
|
<i class="fa fa-paint-brush"></i>
|
|
</button>
|
|
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
|
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
|
</ul>
|
|
|
|
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
|
<i class="fa fa-search"></i>
|
|
</button>
|
|
|
|
</div>
|
|
|
|
<h1 class="menu-title">Easy Rust</h1>
|
|
|
|
<div class="right-buttons">
|
|
|
|
<a href="print.html" title="Print this book" aria-label="Print this book">
|
|
<i id="print-button" class="fa fa-print"></i>
|
|
</a>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div id="search-wrapper" class="hidden">
|
|
<form id="searchbar-outer" class="searchbar-outer">
|
|
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
|
</form>
|
|
<div id="searchresults-outer" class="searchresults-outer hidden">
|
|
<div id="searchresults-header" class="searchresults-header"></div>
|
|
<ul id="searchresults">
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
|
<script type="text/javascript">
|
|
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
|
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
|
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
|
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
|
});
|
|
</script>
|
|
|
|
<div id="content" class="content">
|
|
<main>
|
|
<h2 id="multiple-threads"><a class="header" href="#multiple-threads">Multiple threads</a></h2>
|
|
<p>If you use multiple threads, you can do many things at the same time. Modern computers have more than one core so they can do more than one thing at the same time, and Rust lets you use them. Rust uses threads that are called "OS threads". OS thread means the operating system creates the thread on a different core. (Some other languages use "green threads", which are less powerful)</p>
|
|
<p>You create threads with <code>std::thread::spawn</code> and then a closure to tell it what to do. Threads are interesting because they run at the same time, and you can test it to see what happens. Here is a simple example:</p>
|
|
<pre><pre class="playground"><code class="language-rust">fn main() {
|
|
std::thread::spawn(|| {
|
|
println!("I am printing something");
|
|
});
|
|
}
|
|
</code></pre></pre>
|
|
<p>If you run this, it will be different every time. Sometimes it will print, and sometimes it won't print (this depends on your computer speed too). That is because sometimes <code>main()</code> finishes before the thread finishes. And when <code>main()</code> finishes, the program is over. This is easier to see in a <code>for</code> loop:</p>
|
|
<pre><pre class="playground"><code class="language-rust">fn main() {
|
|
for _ in 0..10 { // set up ten threads
|
|
std::thread::spawn(|| {
|
|
println!("I am printing something");
|
|
});
|
|
} // Now the threads start.
|
|
} // How many can finish before main() ends here?
|
|
</code></pre></pre>
|
|
<p>Usually about four threads will print before <code>main</code> ends, but it is always different. If your computer is faster then it might not print any. Also, sometimes the threads will panic:</p>
|
|
<pre><code class="language-text">thread 'thread 'I am printing something
|
|
thread '<unnamed><unnamed>thread '' panicked at '<unnamed>I am printing something
|
|
' panicked at 'thread '<unnamed>cannot access stdout during shutdown' panicked at '<unnamed>thread 'cannot access stdout during
|
|
shutdown
|
|
</code></pre>
|
|
<p>This is the error when the thread tries to do something right when the program is shutting down.</p>
|
|
<p>You can give the computer something to do so it won't shut down right away:</p>
|
|
<pre><pre class="playground"><code class="language-rust">fn main() {
|
|
for _ in 0..10 {
|
|
std::thread::spawn(|| {
|
|
println!("I am printing something");
|
|
});
|
|
}
|
|
for _ in 0..1_000_000 { // make the program declare "let x = 9" one million times
|
|
// It has to finish this before it can exit the main function
|
|
let _x = 9;
|
|
}
|
|
}
|
|
</code></pre></pre>
|
|
<p>But that is a silly way to give the threads time to finish. The better way is to bind the threads to a variable. If you add <code>let</code>, then you will create a <code>JoinHandle</code>. You can see this in the signature for <code>spawn</code>:</p>
|
|
<pre><code class="language-text">pub fn spawn<F, T>(f: F) -> JoinHandle<T>
|
|
where
|
|
F: FnOnce() -> T,
|
|
F: Send + 'static,
|
|
T: Send + 'static,
|
|
</code></pre>
|
|
<p>(<code>f</code> is the closure - we will learn how to put closures into our functions later)</p>
|
|
<p>So now we have a <code>JoinHandle</code> every time.</p>
|
|
<pre><pre class="playground"><code class="language-rust">fn main() {
|
|
for _ in 0..10 {
|
|
let handle = std::thread::spawn(|| {
|
|
println!("I am printing something");
|
|
});
|
|
|
|
}
|
|
}
|
|
</code></pre></pre>
|
|
<p><code>handle</code> is now a <code>JoinHandle</code>. What do we do with it? We use a method called <code>.join()</code>. This method means "wait until all the threads are done" (it waits for the threads to join it). So now just write <code>handle.join()</code> and it will wait for each of the threads to finish.</p>
|
|
<pre><pre class="playground"><code class="language-rust">fn main() {
|
|
for _ in 0..10 {
|
|
let handle = std::thread::spawn(|| {
|
|
println!("I am printing something");
|
|
});
|
|
|
|
handle.join(); // Wait for the threads to finish
|
|
}
|
|
}
|
|
</code></pre></pre>
|
|
<p>Now we will learn about the three types of closures. The three types are:</p>
|
|
<ul>
|
|
<li><code>FnOnce</code>: takes the whole value</li>
|
|
<li><code>FnMut</code>: takes a mutable reference</li>
|
|
<li><code>Fn</code>: takes a regular reference</li>
|
|
</ul>
|
|
<p>A closure will try to use <code>Fn</code> if it can. But if it needs to change the value it will use <code>FnMut</code>, and if it needs to take the whole value, it will use <code>FnOnce</code>. <code>FnOnce</code> is a good name because it explains what it does: it takes the value once, and then it can't take it again.</p>
|
|
<p>Here is an example:</p>
|
|
<pre><pre class="playground"><code class="language-rust">fn main() {
|
|
let my_string = String::from("I will go into the closure");
|
|
let my_closure = || println!("{}", my_string);
|
|
my_closure();
|
|
my_closure();
|
|
}
|
|
</code></pre></pre>
|
|
<p><code>String</code> is not <code>Copy</code>, so <code>my_closure()</code> is <code>Fn</code>: it takes a reference.</p>
|
|
<p>If we change <code>my_string</code>, it will be <code>FnMut</code>.</p>
|
|
<pre><pre class="playground"><code class="language-rust">fn main() {
|
|
let mut my_string = String::from("I will go into the closure");
|
|
let mut my_closure = || {
|
|
my_string.push_str(" now");
|
|
println!("{}", my_string);
|
|
};
|
|
my_closure();
|
|
my_closure();
|
|
}
|
|
</code></pre></pre>
|
|
<p>This prints:</p>
|
|
<pre><code class="language-text">I will go into the closure now
|
|
I will go into the closure now now
|
|
</code></pre>
|
|
<p>And if you take by value, then it will be <code>FnOnce</code>.</p>
|
|
<pre><pre class="playground"><code class="language-rust">fn main() {
|
|
let my_vec: Vec<i32> = vec![8, 9, 10];
|
|
let my_closure = || {
|
|
my_vec
|
|
.into_iter() // into_iter takes ownership
|
|
.map(|x| x as u8) // turn it into u8
|
|
.map(|x| x * 2) // multiply by 2
|
|
.collect::<Vec<u8>>() // collect into a Vec
|
|
};
|
|
let new_vec = my_closure();
|
|
println!("{:?}", new_vec);
|
|
}
|
|
</code></pre></pre>
|
|
<p>We took by value, so we can't run <code>my_closure()</code> more than once. That is where the name comes from.</p>
|
|
<p>So now back to threads. Let's try to use a value from outside:</p>
|
|
<pre><pre class="playground"><code class="language-rust">fn main() {
|
|
let mut my_string = String::from("Can I go inside the thread?");
|
|
|
|
let handle = std::thread::spawn(|| {
|
|
println!("{}", my_string); // ⚠️
|
|
});
|
|
|
|
handle.join();
|
|
}
|
|
</code></pre></pre>
|
|
<p>The compiler says that this won't work.</p>
|
|
<pre><code class="language-text">error[E0373]: closure may outlive the current function, but it borrows `my_string`, which is owned by the current function
|
|
--> src\main.rs:28:37
|
|
|
|
|
28 | let handle = std::thread::spawn(|| {
|
|
| ^^ may outlive borrowed value `my_string`
|
|
29 | println!("{}", my_string);
|
|
| --------- `my_string` is borrowed here
|
|
|
|
|
note: function requires argument type to outlive `'static`
|
|
--> src\main.rs:28:18
|
|
|
|
|
28 | let handle = std::thread::spawn(|| {
|
|
| __________________^
|
|
29 | | println!("{}", my_string);
|
|
30 | | });
|
|
| |______^
|
|
help: to force the closure to take ownership of `my_string` (and any other referenced variables), use the `move` keyword
|
|
|
|
|
28 | let handle = std::thread::spawn(move || {
|
|
| ^^^^^^^
|
|
</code></pre>
|
|
<p>It is a long message, but helpful: it says to <code>use the `move` keyword</code>. The problem is that we can do anything to <code>my_string</code> while the thread is using it, but it doesn't own it. That would be unsafe.</p>
|
|
<p>Let's try something else that doesn't work:</p>
|
|
<pre><pre class="playground"><code class="language-rust">fn main() {
|
|
let mut my_string = String::from("Can I go inside the thread?");
|
|
|
|
let handle = std::thread::spawn(|| {
|
|
println!("{}", my_string); // now my_string is being used as a reference
|
|
});
|
|
|
|
std::mem::drop(my_string); // ⚠️ We try to drop it here. But the thread still needs it.
|
|
|
|
handle.join();
|
|
}
|
|
</code></pre></pre>
|
|
<p>So you have to take the value with <code>move</code>. Now it is safe:</p>
|
|
<pre><pre class="playground"><code class="language-rust">fn main() {
|
|
let mut my_string = String::from("Can I go inside the thread?");
|
|
|
|
let handle = std::thread::spawn(move|| {
|
|
println!("{}", my_string);
|
|
});
|
|
|
|
std::mem::drop(my_string); // ⚠️ we can't drop, because handle has it. So this won't work
|
|
|
|
handle.join();
|
|
}
|
|
</code></pre></pre>
|
|
<p>So we delete the <code>std::mem::drop</code>, and now it is okay. <code>handle</code> takes <code>my_string</code> and our code is safe.</p>
|
|
<pre><pre class="playground"><code class="language-rust">fn main() {
|
|
let mut my_string = String::from("Can I go inside the thread?");
|
|
|
|
let handle = std::thread::spawn(move|| {
|
|
println!("{}", my_string);
|
|
});
|
|
|
|
handle.join();
|
|
}
|
|
</code></pre></pre>
|
|
<p>So just remember: if you need a value in a thread from outside the thread, you need to use <code>move</code>.</p>
|
|
|
|
</main>
|
|
|
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
|
<!-- Mobile navigation buttons -->
|
|
|
|
<a rel="prev" href="Chapter_45.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|
<i class="fa fa-angle-left"></i>
|
|
</a>
|
|
|
|
|
|
|
|
<a rel="next" href="Chapter_47.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
<i class="fa fa-angle-right"></i>
|
|
</a>
|
|
|
|
|
|
<div style="clear: both"></div>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
|
|
|
<a rel="prev" href="Chapter_45.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|
<i class="fa fa-angle-left"></i>
|
|
</a>
|
|
|
|
|
|
|
|
<a rel="next" href="Chapter_47.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
<i class="fa fa-angle-right"></i>
|
|
</a>
|
|
|
|
</nav>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
|
window.playground_copyable = true;
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
|
|
|
|
|
|
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="book.js" type="text/javascript" charset="utf-8"></script>
|
|
|
|
<!-- Custom JS scripts -->
|
|
|
|
|
|
|
|
|
|
</body>
|
|
</html>
|