763 lines
48 KiB
HTML
763 lines
48 KiB
HTML
|
|
|||
|
<!DOCTYPE html>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<html lang="en">
|
|||
|
<head>
|
|||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|||
|
|
|||
|
<title>6.6. Implicit Threading and Language-based Threads — Computer Systems Fundamentals</title>
|
|||
|
|
|||
|
<link rel="stylesheet" href="_static/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" />
|
|||
|
<link rel="stylesheet" href="_static/css/pygments.css" type="text/css" />
|
|||
|
<link rel="stylesheet" href="_static/css/normalize.css" type="text/css" />
|
|||
|
<link rel="stylesheet" href="../../../JSAV/css/JSAV.css" type="text/css" />
|
|||
|
<link rel="stylesheet" href="../../../lib/odsaMOD-min.css" type="text/css" />
|
|||
|
<link rel="stylesheet" href="_static/css/jquery-1.11.4-smoothness-ui.css" type="text/css" />
|
|||
|
<link rel="stylesheet" href="../../../lib/odsaStyle-min.css" type="text/css" />
|
|||
|
<link rel="stylesheet" href="_static/css/csf.css" type="text/css" />
|
|||
|
|
|||
|
<style>
|
|||
|
.underline { text-decoration: underline; }
|
|||
|
</style>
|
|||
|
|
|||
|
<script type="text/javascript">
|
|||
|
var DOCUMENTATION_OPTIONS = {
|
|||
|
URL_ROOT: './',
|
|||
|
VERSION: '0.4.1',
|
|||
|
COLLAPSE_INDEX: false,
|
|||
|
FILE_SUFFIX: '.html',
|
|||
|
HAS_SOURCE: true
|
|||
|
};
|
|||
|
</script>
|
|||
|
|
|||
|
<script type="text/x-mathjax-config">
|
|||
|
MathJax.Hub.Config({
|
|||
|
tex2jax: {
|
|||
|
inlineMath: [['$','$'], ['\\(','\\)']],
|
|||
|
displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
|
|||
|
processEscapes: true
|
|||
|
},
|
|||
|
"HTML-CSS": {
|
|||
|
scale: "80"
|
|||
|
}
|
|||
|
});
|
|||
|
</script>
|
|||
|
<link rel="shortcut icon" href="_static/favicon.ico"/>
|
|||
|
<link rel="index" title="Index" href="genindex.html" />
|
|||
|
<link rel="search" title="Search" href="search.html" />
|
|||
|
<link rel="index" title="Computer Systems Fundamentals" href="index.html" />
|
|||
|
<link rel="next" title="7. Extended Example: Keyboard Input Listener" href="Extended6Input.html" />
|
|||
|
<link rel="prev" title="5. Thread Arguments and Return Values" href="ThreadArgs.html" />
|
|||
|
|
|||
|
</head><body>
|
|||
|
|
|||
|
<nav class="navbar navbar-expand-md navbar-dark navbar-custom fixed-top">
|
|||
|
|
|||
|
<a class="navbar-brand py-0" href="index.html"><img src="_static/CSF-Logo-Square-Text.png" alt="OpenCSF Logo" height="40em" class="py-1 px-2 mb-0 align-center rounded-lg bg-white" /></a>
|
|||
|
<!-- Show a navbar toggler on mobile -->
|
|||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#defaultNavbars" aria-controls="defaultNavbars" aria-expanded="false" aria-label="Toggle navigation">
|
|||
|
<span class="navbar-toggler-icon"></span>
|
|||
|
</button>
|
|||
|
<div class="collapse navbar-collapse" id="defaultNavbars">
|
|||
|
<ul class="navbar-nav mr-auto">
|
|||
|
<li class="nav-item dropdown">
|
|||
|
<a class="nav-link dropdown-toggle jmu-gold rounded" href="ImplicitThreads.html#" id="navbarDropdownChapters" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Contents</a>
|
|||
|
<div class="dropdown-menu scrollable-menu" role="menu" aria-labelledby="navbarDropdownChapters">
|
|||
|
<a class="dropdown-item" tabindex="-1" href="ImplicitThreads.html#"><b>Chapter 1</b></a>
|
|||
|
<a class="dropdown-item" href="IntroConcSysOverview.html"> 1.1. Introduction to Concurrent Systems</a>
|
|||
|
<a class="dropdown-item" href="SysAndModels.html"> 1.2. Systems and Models</a>
|
|||
|
<a class="dropdown-item" href="Themes.html"> 1.3. Themes and Guiding Principles</a>
|
|||
|
<a class="dropdown-item" href="Architectures.html"> 1.4. System Architectures</a>
|
|||
|
<a class="dropdown-item" href="StateModels.html"> 1.5. State Models in UML</a>
|
|||
|
<a class="dropdown-item" href="SequenceModels.html"> 1.6. Sequence Models in UML</a>
|
|||
|
<a class="dropdown-item" href="StateModelImplementation.html"> 1.7. Extended Example: State Model Implementation</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Chapter 2</b></a>
|
|||
|
<a class="dropdown-item" href="ProcessesOverview.html"> 2.1. Processes and OS Basics</a>
|
|||
|
<a class="dropdown-item" href="Multiprogramming.html"> 2.2. Processes and Multiprogramming</a>
|
|||
|
<a class="dropdown-item" href="KernelMechanics.html"> 2.3. Kernel Mechanics</a>
|
|||
|
<a class="dropdown-item" href="Syscall.html"> 2.4. System Call Interface</a>
|
|||
|
<a class="dropdown-item" href="ProcessCycle.html"> 2.5. Process Life Cycle</a>
|
|||
|
<a class="dropdown-item" href="UnixFile.html"> 2.6. The UNIX File Abstraction</a>
|
|||
|
<a class="dropdown-item" href="EventsSignals.html"> 2.7. Events and Signals</a>
|
|||
|
<a class="dropdown-item" href="Extended2Processes.html"> 2.8. Extended Example: Listing Files with Processes</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Chapter 3</b></a>
|
|||
|
<a class="dropdown-item" href="IPCOverview.html"> 3.1. Concurrency with IPC</a>
|
|||
|
<a class="dropdown-item" href="IPCModels.html"> 3.2. IPC Models</a>
|
|||
|
<a class="dropdown-item" href="Pipes.html"> 3.3. Pipes and FIFOs</a>
|
|||
|
<a class="dropdown-item" href="MMap.html"> 3.4. Shared Memory With Memory-mapped Files</a>
|
|||
|
<a class="dropdown-item" href="POSIXvSysV.html"> 3.5. POSIX vs. System V IPC</a>
|
|||
|
<a class="dropdown-item" href="MQueues.html"> 3.6. Message Passing With Message Queues</a>
|
|||
|
<a class="dropdown-item" href="ShMem.html"> 3.7. Shared Memory</a>
|
|||
|
<a class="dropdown-item" href="IPCSems.html"> 3.8. Semaphores</a>
|
|||
|
<a class="dropdown-item" href="Extended3Bash.html"> 3.9. Extended Example: Bash-lite: A Simple Command-line Shell</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Chapter 4</b></a>
|
|||
|
<a class="dropdown-item" href="SocketsOverview.html"> 4.1. Networked Concurrency</a>
|
|||
|
<a class="dropdown-item" href="FiveLayer.html"> 4.2. The TCP/IP Internet Model</a>
|
|||
|
<a class="dropdown-item" href="NetApps.html"> 4.3. Network Applications and Protocols</a>
|
|||
|
<a class="dropdown-item" href="Sockets.html"> 4.4. The Socket Interface</a>
|
|||
|
<a class="dropdown-item" href="TCPSockets.html"> 4.5. TCP Socket Programming: HTTP</a>
|
|||
|
<a class="dropdown-item" href="UDPSockets.html"> 4.6. UDP Socket Programming: DNS</a>
|
|||
|
<a class="dropdown-item" href="AppBroadcast.html"> 4.7. Application-Layer Broadcasting: DHCP</a>
|
|||
|
<a class="dropdown-item" href="Extended4CGI.html"> 4.8. Extended Example: CGI Web Server</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Chapter 5</b></a>
|
|||
|
<a class="dropdown-item" href="InternetOverview.html"> 5.1. The Internet and Connectivity</a>
|
|||
|
<a class="dropdown-item" href="AppLayer.html"> 5.2. Application Layer: Overlay Networks</a>
|
|||
|
<a class="dropdown-item" href="TransLayer.html"> 5.3. Transport Layer</a>
|
|||
|
<a class="dropdown-item" href="NetSec.html"> 5.4. Network Security Fundamentals</a>
|
|||
|
<a class="dropdown-item" href="NetLayer.html"> 5.5. Network Layer: IP</a>
|
|||
|
<a class="dropdown-item" href="LinkLayer.html"> 5.6. Link Layer</a>
|
|||
|
<a class="dropdown-item" href="Wireless.html"> 5.7. Wireless Connectivity: Wi-Fi, Bluetooth, and Zigbee</a>
|
|||
|
<a class="dropdown-item" href="Extended5DNS.html"> 5.8. Extended Example: DNS client</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Chapter 6</b></a>
|
|||
|
<a class="dropdown-item" href="ThreadsOverview.html"> 6.1. Concurrency with Multithreading</a>
|
|||
|
<a class="dropdown-item" href="ProcVThreads.html"> 6.2. Processes vs. Threads</a>
|
|||
|
<a class="dropdown-item" href="RaceConditions.html"> 6.3. Race Conditions and Critical Sections</a>
|
|||
|
<a class="dropdown-item" href="POSIXThreads.html"> 6.4. POSIX Thread Library</a>
|
|||
|
<a class="dropdown-item" href="ThreadArgs.html"> 6.5. Thread Arguments and Return Values</a>
|
|||
|
<a class="dropdown-item" href="ImplicitThreads.html"> 6.6. Implicit Threading and Language-based Threads</a>
|
|||
|
<a class="dropdown-item" href="Extended6Input.html"> 6.7. Extended Example: Keyboard Input Listener</a>
|
|||
|
<a class="dropdown-item" href="Extended6Primes.html"> 6.8. Extended Example: Concurrent Prime Number Search</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Chapter 7</b></a>
|
|||
|
<a class="dropdown-item" href="SynchOverview.html"> 7.1. Synchronization Primitives</a>
|
|||
|
<a class="dropdown-item" href="CritSect.html"> 7.2. Critical Sections and Peterson's Solution</a>
|
|||
|
<a class="dropdown-item" href="Locks.html"> 7.3. Locks</a>
|
|||
|
<a class="dropdown-item" href="Semaphores.html"> 7.4. Semaphores</a>
|
|||
|
<a class="dropdown-item" href="Barriers.html"> 7.5. Barriers</a>
|
|||
|
<a class="dropdown-item" href="Condvars.html"> 7.6. Condition Variables</a>
|
|||
|
<a class="dropdown-item" href="Deadlock.html"> 7.7. Deadlock</a>
|
|||
|
<a class="dropdown-item" href="Extended7Events.html"> 7.8. Extended Example: Event Log File</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Chapter 8</b></a>
|
|||
|
<a class="dropdown-item" href="SynchProblemsOverview.html"> 8.1. Synchronization Patterns and Problems</a>
|
|||
|
<a class="dropdown-item" href="SynchDesign.html"> 8.2. Basic Synchronization Design Patterns</a>
|
|||
|
<a class="dropdown-item" href="ProdCons.html"> 8.3. Producer-Consumer Problem</a>
|
|||
|
<a class="dropdown-item" href="ReadWrite.html"> 8.4. Readers-Writers Problem</a>
|
|||
|
<a class="dropdown-item" href="DiningPhil.html"> 8.5. Dining Philosophers Problem and Deadlock</a>
|
|||
|
<a class="dropdown-item" href="CigSmokers.html"> 8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks</a>
|
|||
|
<a class="dropdown-item" href="Extended8ModExp.html"> 8.7. Extended Example: Parallel Modular Exponentiation</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Chapter 9</b></a>
|
|||
|
<a class="dropdown-item" href="ParallelDistributedOverview.html"> 9.1. Parallel and Distributed Systems</a>
|
|||
|
<a class="dropdown-item" href="ParVConc.html"> 9.2. Parallelism vs. Concurrency</a>
|
|||
|
<a class="dropdown-item" href="ParallelDesign.html"> 9.3. Parallel Design Patterns</a>
|
|||
|
<a class="dropdown-item" href="Scaling.html"> 9.4. Limits of Parallelism and Scaling</a>
|
|||
|
<a class="dropdown-item" href="DistTiming.html"> 9.5. Timing in Distributed Environments</a>
|
|||
|
<a class="dropdown-item" href="DistDataStorage.html"> 9.6. Reliable Data Storage and Location</a>
|
|||
|
<a class="dropdown-item" href="DistConsensus.html"> 9.7. Consensus in Distributed Systems</a>
|
|||
|
<a class="dropdown-item" href="Extended9Blockchain.html"> 9.8. Extended Example: Blockchain Proof-of-Work</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Appendix A</b></a>
|
|||
|
<a class="dropdown-item" href="CLangOverview.html"> A.1. C Language Reintroduction</a>
|
|||
|
<a class="dropdown-item" href="Debugging.html"> A.2. Documentation and Debugging</a>
|
|||
|
<a class="dropdown-item" href="BasicTypes.html"> A.3. Basic Types and Pointers</a>
|
|||
|
<a class="dropdown-item" href="Arrays.html"> A.4. Arrays, Structs, Enums, and Type Definitions</a>
|
|||
|
<a class="dropdown-item" href="Functions.html"> A.5. Functions and Scope</a>
|
|||
|
<a class="dropdown-item" href="Pointers.html"> A.6. Pointers and Dynamic Allocation</a>
|
|||
|
<a class="dropdown-item" href="Strings.html"> A.7. Strings</a>
|
|||
|
<a class="dropdown-item" href="FunctionPointers.html"> A.8. Function Pointers</a>
|
|||
|
<a class="dropdown-item" href="Files.html"> A.9. Files</a>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
|
|||
|
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
|||
|
<li class="nav-item"><a class="nav-link jmu-gold" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/source/ImplicitThreads.rst"
|
|||
|
target="_blank" rel="nofollow">Show Source</a></li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</nav>
|
|||
|
|
|||
|
|
|||
|
<div class="container center">
|
|||
|
«  <a id="prevmod" href="ThreadArgs.html">6.5. Thread Arguments and Return Values</a>
|
|||
|
  ::  
|
|||
|
<a class="uplink" href="index.html">Contents</a>
|
|||
|
  ::  
|
|||
|
<a id="nextmod" href="Extended6Input.html">6.7. Extended Example: Keyboard Input Listener</a>  »
|
|||
|
|
|||
|
</div>
|
|||
|
<br />
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<script type="text/javascript" src="_static/js/jquery-2.1.4.min.js"></script>
|
|||
|
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
|||
|
<script type="text/javascript" src="_static/js/jquery-1.11.4-ui.min.js"></script>
|
|||
|
<script type="text/javascript" src="_static/js/forge-0.7.0.min.js"></script>
|
|||
|
<script type="text/javascript" src="../../../JSAV/lib/jquery.transit.js"></script>
|
|||
|
<script type="text/javascript" src="../../../JSAV/lib/raphael.js"></script>
|
|||
|
<script type="text/javascript" src="../../../JSAV/build/JSAV-min.js"></script>
|
|||
|
<script type="text/javascript" src="_static/js/config.js"></script>
|
|||
|
<script type="text/javascript" src="../../../lib/odsaUtils-min.js"></script>
|
|||
|
<script type="text/javascript" src="../../../lib/odsaMOD-min.js"></script>
|
|||
|
<script type="text/javascript" src="_static/js/d3-4.13.0.min.js"></script>
|
|||
|
<script type="text/javascript" src="_static/js/d3-selection-multi.v1.min.js"></script>
|
|||
|
<script type="text/javascript" src="../../../lib/dataStructures.js"></script>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="container">
|
|||
|
|
|||
|
<script>ODSA.SETTINGS.DISP_MOD_COMP = true;ODSA.SETTINGS.MODULE_NAME = "ImplicitThreads";ODSA.SETTINGS.MODULE_LONG_NAME = "Implicit Threading and Language-based Threads";ODSA.SETTINGS.MODULE_CHAPTER = "Concurrency with Multithreading"; ODSA.SETTINGS.BUILD_DATE = "2021-06-01 15:31:50"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script><div class="section" id="implicit-threading-and-language-based-threads">
|
|||
|
<h1>6.6. Implicit Threading and Language-based Threads<a class="headerlink" href="ImplicitThreads.html#implicit-threading-and-language-based-threads" title="Permalink to this headline">¶</a></h1>
|
|||
|
<p>The POSIX thread library is a powerful and robust mechanism for concurrent
|
|||
|
systems programming. However, the library places a significant burden on the
|
|||
|
programmer to ensure that the implementation avoids race conditions and other
|
|||
|
bugs. In <a class="reference external" href="SynchProblemsOverview.html">Synchronization Problems</a>, we will
|
|||
|
examine common patterns that emerge in these types of programs and how to avoid subtle errors.</p>
|
|||
|
<p>Since threads were first introduced, language designers have explored a number
|
|||
|
of techniques that reduce the complexity and responsibility of managing threads.
|
|||
|
This section will examine three different approaches for making multithreading
|
|||
|
easier. The first approach is a general style called <a class="reference internal" href="Glossary.html#term-implicit-threading"><span class="xref std std-term">implicit threading</span></a>
|
|||
|
which aims to hide the management of threads as much as possible. The second
|
|||
|
approach is to treat threads as objects in languages like Java and Python. The
|
|||
|
third (and most modern) approach is to design the language around the concept of
|
|||
|
concurrency as a fundamental feature.</p>
|
|||
|
<div class="section" id="implicit-threading-with-openmp">
|
|||
|
<h2>6.6.1. Implicit Threading with OpenMP<a class="headerlink" href="ImplicitThreads.html#implicit-threading-with-openmp" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>Implicit threading is the use of libraries or other language support to hide the
|
|||
|
management of threads. In the context of C, the most common implicit threading
|
|||
|
library is <a class="reference internal" href="Glossary.html#term-openmp"><span class="xref std std-term">OpenMP</span></a>. OpenMP uses the <code class="docutils literal notranslate"><span class="pre">#pragma</span></code> compiler directive to
|
|||
|
detect and insert additional library code at compile time. As an example,
|
|||
|
consider the prime number calculator from the Extended Examples.
|
|||
|
<a class="reference external" href="ImplicitThreads.html#cl6-17">Code Listing 6.17</a> shows the OpenMP equivalent.</p>
|
|||
|
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl6-17"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 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</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 6.17:</span>
|
|||
|
<span class="cm"> OpenMP can make some multithreading trivial to implement</span>
|
|||
|
<span class="cm"> */</span>
|
|||
|
|
|||
|
<span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp"></span>
|
|||
|
<span class="cp">#include</span> <span class="cpf"><stdbool.h></span><span class="cp"></span>
|
|||
|
<span class="cp">#include</span> <span class="cpf"><omp.h></span><span class="cp"></span>
|
|||
|
|
|||
|
<span class="kt">int</span>
|
|||
|
<span class="nf">main</span> <span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span>
|
|||
|
<span class="p">{</span>
|
|||
|
<span class="cm">/* Set up the overall algorithm parameters */</span>
|
|||
|
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">end</span> <span class="o">=</span> <span class="mi">100000000L</span><span class="p">;</span>
|
|||
|
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">iter</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
|
|||
|
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="cm">/* OpenMP parallel for-loop with reduction on count. Each thread</span>
|
|||
|
<span class="cm"> will have its own count, but they'll be combined when all</span>
|
|||
|
<span class="cm"> threads are done. */</span>
|
|||
|
<span class="cp">#pragma omp parallel for default(shared) private(iter) \</span>
|
|||
|
<span class="cp"> reduction(+:count)</span>
|
|||
|
<span class="k">for</span> <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">alue</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="n">value</span> <span class="o"><</span> <span class="n">end</span><span class="p">;</span> <span class="n">value</span><span class="o">++</span><span class="p">)</span>
|
|||
|
<span class="p">{</span>
|
|||
|
<span class="kt">bool</span> <span class="n">is_prime</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
|
|||
|
<span class="k">for</span> <span class="p">(</span><span class="n">iter</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="n">iter</span> <span class="o">*</span> <span class="n">iter</span> <span class="o"><=</span> <span class="n">value</span> <span class="o">&&</span> <span class="n">is_prime</span><span class="p">;</span> <span class="n">iter</span><span class="o">++</span><span class="p">)</span>
|
|||
|
<span class="k">if</span> <span class="p">(</span><span class="n">value</span> <span class="o">%</span> <span class="n">iter</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
|
|||
|
<span class="n">is_prime</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
|
|||
|
<span class="k">if</span> <span class="p">(</span><span class="n">is_prime</span><span class="p">)</span>
|
|||
|
<span class="n">count</span><span class="o">++</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="n">printf</span> <span class="p">(</span><span class="s">"Total number of primes less than %ld: %ld</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">end</span><span class="p">,</span>
|
|||
|
<span class="n">count</span><span class="p">);</span>
|
|||
|
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
|
|||
|
<span class="p">}</span>
|
|||
|
</pre></div>
|
|||
|
</td></tr></table></div>
|
|||
|
<p>With implicit threading, the focus of the programmer is on writing the algorithm
|
|||
|
rather than the multithreading. The OpenMP library itself takes care of managing
|
|||
|
the threads. Specifically, the <code class="docutils literal notranslate"><span class="pre">#pragma</span></code> line indicates that OpenMP (<code class="docutils literal notranslate"><span class="pre">omp</span></code>)
|
|||
|
should parallelize a for-loop (<code class="docutils literal notranslate"><span class="pre">parallel</span> <span class="pre">for</span></code>) with some constraints on the
|
|||
|
variables. The OpenMP implementation on that system will then inject code to
|
|||
|
perform the thread creation and join.</p>
|
|||
|
<p>OpenMP in C is built on top of the pthread library. As such, any code that can
|
|||
|
be written using OpenMP can be converted into a more verbose pthread equivalent.
|
|||
|
However, the disadvantage of OpenMP is that it only works for certain types of
|
|||
|
tasks. There are many types of programs, such as the keyboard listener example,
|
|||
|
that can be implemented in pthreads but not OpenMP.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="threads-as-objects">
|
|||
|
<h2>6.6.2. Threads as Objects<a class="headerlink" href="ImplicitThreads.html#threads-as-objects" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>In other languages, traditional object-oriented languages provide explicit
|
|||
|
multithreading support with threads as objects. In these types of languages,
|
|||
|
classes are written to either extend a thread class or implement a corresponding
|
|||
|
interface. This style resembles the pthread approach, as the code is written
|
|||
|
with explicit thread management. However, the encapsulation of data within the
|
|||
|
classes and additional synchronization features simplify the task.</p>
|
|||
|
<div class="section" id="java-threads">
|
|||
|
<h3>6.6.2.1. Java Threads<a class="headerlink" href="ImplicitThreads.html#java-threads" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>Java provides both a <code class="docutils literal notranslate"><span class="pre">Thread</span></code> class and a <code class="docutils literal notranslate"><span class="pre">Runnable</span></code> interface that can be
|
|||
|
used, as shown in <a class="reference external" href="ImplicitThreads.html#cl6-18">Code Listing 6.18</a>. Both require implementing a
|
|||
|
public void <code class="docutils literal notranslate"><span class="pre">run()</span></code> method that defines the entry point of the thread. Once an
|
|||
|
instance of the object is allocated, the thread can be started by invoking the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">start()</span></code> method on it. As with pthreads, starting the thread is asynchronous,
|
|||
|
so the timing of the execution is nondeterministic.</p>
|
|||
|
<div class="highlight-java border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl6-18"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 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</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 6.18:</span>
|
|||
|
<span class="cm"> Java offers both a class and an interface to support threads as objects</span>
|
|||
|
<span class="cm"> */</span>
|
|||
|
|
|||
|
<span class="kd">class</span> <span class="nc">ThreadExtender</span> <span class="kd">extends</span> <span class="n">Thread</span> <span class="o">{</span>
|
|||
|
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="o">()</span> <span class="o">{</span>
|
|||
|
<span class="cm">/* Implement code here */</span>
|
|||
|
<span class="o">}</span>
|
|||
|
<span class="o">}</span>
|
|||
|
|
|||
|
<span class="kd">class</span> <span class="nc">RunImplement</span> <span class="kd">implements</span> <span class="n">Runnable</span> <span class="o">{</span>
|
|||
|
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="o">()</span> <span class="o">{</span>
|
|||
|
<span class="cm">/* Implement code here */</span>
|
|||
|
<span class="o">}</span>
|
|||
|
<span class="o">}</span>
|
|||
|
|
|||
|
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span> <span class="n">args</span><span class="o">[])</span> <span class="o">{</span>
|
|||
|
<span class="cm">/* Instantiate the ThreadExtender and start it */</span>
|
|||
|
<span class="n">ThreadExtender</span> <span class="n">te</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ThreadExtender</span><span class="o">();</span>
|
|||
|
<span class="n">te</span><span class="o">.</span><span class="na">start</span><span class="o">();</span>
|
|||
|
|
|||
|
<span class="cm">/* Instantiate the Runnable version and start it */</span>
|
|||
|
<span class="n">RunImplement</span> <span class="n">ri</span> <span class="o">=</span> <span class="k">new</span> <span class="n">RunImplement</span><span class="o">();</span>
|
|||
|
<span class="n">Thread</span> <span class="n">t</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Thread</span><span class="o">(</span><span class="n">ri</span><span class="o">);</span>
|
|||
|
<span class="n">t</span><span class="o">.</span><span class="na">start</span><span class="o">();</span>
|
|||
|
|
|||
|
<span class="cm">/* Join the threads */</span>
|
|||
|
<span class="n">te</span><span class="o">.</span><span class="na">join</span><span class="o">();</span>
|
|||
|
<span class="n">j</span><span class="o">.</span><span class="na">join</span><span class="o">();</span>
|
|||
|
<span class="o">}</span>
|
|||
|
</pre></div>
|
|||
|
</td></tr></table></div>
|
|||
|
</div>
|
|||
|
<div class="section" id="python-threads">
|
|||
|
<h3>6.6.2.2. Python Threads<a class="headerlink" href="ImplicitThreads.html#python-threads" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p><a class="reference external" href="ImplicitThreads.html#cl6-19">Code Listing 6.19</a> demonstrates two mechanisms for multithreading in
|
|||
|
Python. One approach is similar to the pthread style, where a function name is
|
|||
|
passed to a library method <code class="docutils literal notranslate"><span class="pre">thread.start_new_thread()</span></code>. This approach is very
|
|||
|
limited and lacks the ability to join or terminate the thread after it starts. A
|
|||
|
more flexible technique is to use the threading module to define a class that
|
|||
|
extends threading. Similar to the Java approach, the class must have a <code class="docutils literal notranslate"><span class="pre">run()</span></code>
|
|||
|
method that provides the thread’s entry point. Once an object is instantiated
|
|||
|
from this class, it can be explicitly started and joined later.</p>
|
|||
|
<div class="highlight-python border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl6-19"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 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</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="c1"># Code Listing 6.19:</span>
|
|||
|
<span class="c1"># Python offers a pthread-like interface and an object-oriented module for threading */</span>
|
|||
|
|
|||
|
<span class="c1">#!/usr/bin/python</span>
|
|||
|
|
|||
|
<span class="kn">import</span> <span class="nn">thread</span>
|
|||
|
<span class="kn">import</span> <span class="nn">threading</span>
|
|||
|
<span class="kn">import</span> <span class="nn">time</span>
|
|||
|
|
|||
|
<span class="c1"># Low-level procedural approach with the thread module</span>
|
|||
|
<span class="k">def</span> <span class="nf">proc_thread</span> <span class="p">(</span><span class="n">name</span><span class="p">):</span>
|
|||
|
<span class="c1"># thread code here</span>
|
|||
|
<span class="k">print</span> <span class="s2">"Ran thread "</span> <span class="o">+</span> <span class="n">name</span>
|
|||
|
|
|||
|
<span class="c1"># Use thread module to create and start the thread</span>
|
|||
|
<span class="k">try</span><span class="p">:</span>
|
|||
|
<span class="n">thread</span><span class="o">.</span><span class="n">start_new_thread</span><span class="p">(</span><span class="n">proc_thread</span><span class="p">,</span> <span class="p">(</span><span class="s2">"First Thread"</span><span class="p">,</span> <span class="p">))</span>
|
|||
|
<span class="k">except</span><span class="p">:</span>
|
|||
|
<span class="k">print</span> <span class="s2">"Failed to start thread"</span>
|
|||
|
|
|||
|
<span class="c1"># OOP approach using the threading module</span>
|
|||
|
<span class="k">class</span> <span class="nc">ObjThread</span> <span class="p">(</span><span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">):</span>
|
|||
|
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
|
|||
|
<span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|||
|
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
|
|||
|
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|||
|
<span class="c1"># Thread entry point here</span>
|
|||
|
<span class="k">print</span> <span class="s2">"Running object thread "</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>
|
|||
|
|
|||
|
<span class="c1"># Create an instance of the object to start and join</span>
|
|||
|
<span class="n">threadObj</span> <span class="o">=</span> <span class="n">ObjThread</span><span class="p">(</span><span class="s2">"Second Thread"</span><span class="p">)</span>
|
|||
|
<span class="n">threadObj</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
|||
|
<span class="n">threadObj</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
|
|||
|
|
|||
|
<span class="c1"># Delay to make sure both run</span>
|
|||
|
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</td></tr></table></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="section" id="concurrency-as-language-design">
|
|||
|
<h2>6.6.3. Concurrency as Language Design<a class="headerlink" href="ImplicitThreads.html#concurrency-as-language-design" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>Languages such as C, Java, and Python were all designed before <a class="reference internal" href="Glossary.html#term-multicore"><span class="xref std std-term">multicore</span></a>
|
|||
|
architectures rose to prominence in the early 2000s. As such, multithreading
|
|||
|
support in these languages was added as a supplement to the language, rather
|
|||
|
than a core feature. These languages were originally designed for a
|
|||
|
uniprocessing procedural or object-oriented paradigm. As a result, the memory
|
|||
|
models that underlie these languages are not adequate to prevent race
|
|||
|
conditions. The multithreading libraries had to provide additional features that
|
|||
|
allowed programmers to synchronize access to shared data. Or, put another way,
|
|||
|
programmers were forced to do extra work to make their programs work correctly.</p>
|
|||
|
<p>Newer programming languages have avoided this problem by building assumptions of
|
|||
|
concurrent execution directly into the language design itself. For instance, Go
|
|||
|
combines a trivial implicit threading technique (goroutines) with channels, a
|
|||
|
well-defined form of message-passing communication. Rust adopts an explicit
|
|||
|
threading approach similar to pthreads. However, Rust has very strong memory
|
|||
|
protections that require no additional work by the programmer.</p>
|
|||
|
<div class="section" id="goroutines">
|
|||
|
<h3>6.6.3.1. Goroutines<a class="headerlink" href="ImplicitThreads.html#goroutines" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>The Go language includes a trivial mechanism for implicit threading: place the
|
|||
|
keyword go before a function call. In <a class="reference external" href="ImplicitThreads.html#cl6-20">Code Listing 6.20</a>, the line
|
|||
|
go <code class="docutils literal notranslate"><span class="pre">keyboard_listener(messages)</span></code> launches a new thread that will execute the
|
|||
|
keyboard listener function. The new thread is passed a connection to a
|
|||
|
message-passing <em>channel</em>. Then, the main thread calls
|
|||
|
<code class="docutils literal notranslate"><span class="pre">success</span> <span class="pre">:=</span> <span class="pre"><-messages</span></code>, which performs a blocking read on the channel. Once
|
|||
|
the user has entered the correct guess of 7, the keyboard listener thread writes
|
|||
|
to the channel, allowing the main thread to progress.</p>
|
|||
|
<p>Channels and <a class="reference internal" href="Glossary.html#term-goroutine"><span class="xref std std-term">goroutines</span></a> are core parts of the Go language,
|
|||
|
which was designed under the assumption that most programs would be
|
|||
|
multithreaded. This design choice streamlines the development model, allowing
|
|||
|
the language itself to bear the responsibility for managing the threads and scheduling.</p>
|
|||
|
<div class="highlight-go border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl6-20"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 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</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 6.20:</span>
|
|||
|
<span class="cm"> Go provides built-in concurrency techniques with goroutines and channels for communication</span>
|
|||
|
<span class="cm">*/</span>
|
|||
|
|
|||
|
<span class="kn">package</span> <span class="nx">main</span>
|
|||
|
|
|||
|
<span class="kn">import</span> <span class="p">(</span>
|
|||
|
<span class="s">"bufio"</span>
|
|||
|
<span class="s">"fmt"</span>
|
|||
|
<span class="s">"os"</span>
|
|||
|
<span class="s">"strconv"</span>
|
|||
|
<span class="s">"strings"</span>
|
|||
|
<span class="p">)</span>
|
|||
|
|
|||
|
<span class="cm">/* Main program entry point */</span>
|
|||
|
<span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
|
|||
|
<span class="cm">/* Create a channel for communication */</span>
|
|||
|
<span class="nx">messages</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">string</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Print</span><span class="p">(</span><span class="s">"Guess a number between 1 and 10: "</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="cm">/* Start keyboard listener as a goroutine with the channel */</span>
|
|||
|
<span class="k">go</span> <span class="nx">keyboard_listener</span><span class="p">(</span><span class="nx">messages</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="cm">/* Wait until there is data in the channel */</span>
|
|||
|
<span class="nx">success</span> <span class="o">:=</span> <span class="o"><-</span><span class="nx">messages</span>
|
|||
|
<span class="k">if</span> <span class="nx">success</span> <span class="o">==</span> <span class="s">"true"</span> <span class="p">{</span>
|
|||
|
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">"You must have guess 7."</span><span class="p">)</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="cm">/* Define the keyboard listener thread with channel back to main */</span>
|
|||
|
<span class="kd">func</span> <span class="nx">keyboard_listener</span><span class="p">(</span><span class="nx">messages</span> <span class="kd">chan</span> <span class="kt">string</span><span class="p">)</span> <span class="p">{</span>
|
|||
|
<span class="nx">stdin</span> <span class="o">:=</span> <span class="nx">bufio</span><span class="p">.</span><span class="nx">NewReader</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Stdin</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="cm">/* Loop forever, reading keyboard input */</span>
|
|||
|
<span class="k">for</span> <span class="p">{</span>
|
|||
|
<span class="nx">text</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">stdin</span><span class="p">.</span><span class="nx">ReadString</span><span class="p">(</span><span class="sc">'\n'</span><span class="p">)</span>
|
|||
|
|
|||
|
<span class="cm">/* Try to convert the input text to an int 7 */</span>
|
|||
|
<span class="nx">value</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span>
|
|||
|
<span class="nx">strconv</span><span class="p">.</span><span class="nx">ParseInt</span><span class="p">(</span><span class="nx">strings</span><span class="p">.</span><span class="nx">Trim</span><span class="p">(</span><span class="nx">text</span><span class="p">,</span> <span class="s">"\n"</span><span class="p">),</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">32</span><span class="p">)</span>
|
|||
|
<span class="k">if</span> <span class="nx">err</span> <span class="o">==</span> <span class="kc">nil</span> <span class="p">{</span>
|
|||
|
<span class="k">if</span> <span class="nx">value</span> <span class="o">==</span> <span class="mi">7</span> <span class="p">{</span>
|
|||
|
<span class="cm">/* Success. Send a message back through</span>
|
|||
|
<span class="cm"> the channel and exit */</span>
|
|||
|
<span class="nx">messages</span> <span class="o"><-</span> <span class="s">"true"</span>
|
|||
|
<span class="k">return</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Print</span><span class="p">(</span><span class="s">"Wrong. Try again. "</span><span class="p">)</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="p">}</span>
|
|||
|
</pre></div>
|
|||
|
</td></tr></table></div>
|
|||
|
</div>
|
|||
|
<div class="section" id="rust-concurrency">
|
|||
|
<h3>6.6.3.2. Rust Concurrency<a class="headerlink" href="ImplicitThreads.html#rust-concurrency" title="Permalink to this headline">¶</a></h3>
|
|||
|
<p>Rust is another language that has been created in recent years, with concurrency
|
|||
|
as a central design feature. <a class="reference external" href="ImplicitThreads.html#cl6-21">Code Listing 6.21</a> illustrates the use
|
|||
|
of <code class="docutils literal notranslate"><span class="pre">thread::spawn()</span></code> to create a new thread, which can later be joined by
|
|||
|
invoking <code class="docutils literal notranslate"><span class="pre">join()</span></code> on it. The argument to <code class="docutils literal notranslate"><span class="pre">thread::spawn()</span></code> beginning at the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">||</span></code> is known as a closure, which can be thought of as an anonymous function.
|
|||
|
That is, the child thread here will print the value of <code class="docutils literal notranslate"><span class="pre">x</span></code>.</p>
|
|||
|
<div class="highlight-rust border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl6-21"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
|||
|
2
|
|||
|
3
|
|||
|
4
|
|||
|
5
|
|||
|
6
|
|||
|
7
|
|||
|
8
|
|||
|
9
|
|||
|
10
|
|||
|
11
|
|||
|
12
|
|||
|
13
|
|||
|
14
|
|||
|
15
|
|||
|
16
|
|||
|
17
|
|||
|
18
|
|||
|
19
|
|||
|
20
|
|||
|
21
|
|||
|
22
|
|||
|
23
|
|||
|
24</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 6.21:</span>
|
|||
|
<span class="cm"> Rust threads can be created with anonymous functions known as closure</span>
|
|||
|
<span class="cm"> */</span><span class="w"></span>
|
|||
|
|
|||
|
<span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">thread</span><span class="p">;</span><span class="w"></span>
|
|||
|
|
|||
|
<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
|
|||
|
<span class="w"> </span><span class="cm">/* Initialize a mutable variable x to 10 */</span><span class="w"></span>
|
|||
|
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">10</span><span class="p">;</span><span class="w"></span>
|
|||
|
|
|||
|
<span class="w"> </span><span class="cm">/* Spawn a new thread */</span><span class="w"></span>
|
|||
|
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">child_thread</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">thread</span>::<span class="n">spawn</span><span class="p">(</span><span class="k">move</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="p">{</span><span class="w"> </span>
|
|||
|
<span class="w"> </span><span class="cm">/* Make the thread sleep for one second, then print x */</span><span class="w"></span>
|
|||
|
<span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span>
|
|||
|
<span class="w"> </span><span class="n">println</span><span class="o">!</span><span class="p">(</span><span class="s">"x = {}"</span><span class="p">,</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"></span>
|
|||
|
<span class="w"> </span><span class="p">});</span><span class="w"></span>
|
|||
|
|
|||
|
<span class="w"> </span><span class="cm">/* Change x in the main thread and print it */</span><span class="w"></span>
|
|||
|
<span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span>
|
|||
|
<span class="w"> </span><span class="n">println</span><span class="o">!</span><span class="p">(</span><span class="s">"x = {}"</span><span class="p">,</span><span class="w"> </span><span class="n">x</span><span class="p">);</span><span class="w"></span>
|
|||
|
|
|||
|
<span class="w"> </span><span class="cm">/* Join the thread and print x again */</span><span class="w"></span>
|
|||
|
<span class="w"> </span><span class="n">child_thread</span><span class="p">.</span><span class="n">join</span><span class="p">();</span><span class="w"></span>
|
|||
|
<span class="p">}</span><span class="w"></span>
|
|||
|
</pre></div>
|
|||
|
</td></tr></table></div>
|
|||
|
<p>However, there is a subtle point in this code that is central to Rust’s design.
|
|||
|
Within the new thread (executing the code in the closure), the <code class="docutils literal notranslate"><span class="pre">x</span></code> variable is
|
|||
|
distinct from the <code class="docutils literal notranslate"><span class="pre">x</span></code> in other parts of this code. Rust enforces a very strict
|
|||
|
memory model (known as <em>ownership</em>) which prevents multiple threads from
|
|||
|
accessing the same memory. In this example, the move keyword indicates that the
|
|||
|
spawned thread will receive a separate copy of <code class="docutils literal notranslate"><span class="pre">x</span></code> for its own use. Regardless
|
|||
|
of the scheduling of the two threads, the main and child threads cannot
|
|||
|
interfere with each other’s modifications of <code class="docutils literal notranslate"><span class="pre">x</span></code>, because they are distinct
|
|||
|
copies. It is impossible for the two threads to share access to the same memory.</p>
|
|||
|
<p>In this small example, the issue of ownership may not seem to be a big deal.
|
|||
|
However, if you learn more about Rust and concurrency, you’ll quickly realize
|
|||
|
that it is. Ownership makes Rust very unique and makes it a very powerful
|
|||
|
language for concurrent programming. The crux is that ownership completely
|
|||
|
eliminates several types of race conditions, since it is impossible for multiple
|
|||
|
threads to share the same memory location. Furthermore, it achieves this memory
|
|||
|
safety <strong>without imposing any run-time performance penalty</strong>. Ownership
|
|||
|
constraints are checked and enforced at compile-time. This combination of memory
|
|||
|
safety and efficient performance gives Rust a significant advantage over other
|
|||
|
languages in regard to multithreading.</p>
|
|||
|
<div
|
|||
|
id="ImplicitThreadSumm"
|
|||
|
class="embedContainer"
|
|||
|
data-exer-name="ImplicitThreadSumm"
|
|||
|
data-long-name="Implicit threading questions"
|
|||
|
data-short-name="ImplicitThreadSumm"
|
|||
|
data-frame-src="../../../Exercises/Threads/ImplicitThreadSumm.html?selfLoggingEnabled=false&localMode=true&module=ImplicitThreads&JXOP-debug=true&JOP-lang=en&JXOP-code=java"
|
|||
|
data-frame-width="950"
|
|||
|
data-frame-height="550"
|
|||
|
data-external="false"
|
|||
|
data-points="1.0"
|
|||
|
data-required="True"
|
|||
|
data-showhide="show"
|
|||
|
data-threshold="4"
|
|||
|
data-type="ka"
|
|||
|
data-exer-id="">
|
|||
|
|
|||
|
<div class="center">
|
|||
|
<div id="ImplicitThreadSumm_iframe"></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="container">
|
|||
|
|
|||
|
<div class="mt-4 container center">
|
|||
|
«  <a id="prevmod1" href="ThreadArgs.html">6.5. Thread Arguments and Return Values</a>
|
|||
|
  ::  
|
|||
|
<a class="uplink" href="index.html">Contents</a>
|
|||
|
  ::  
|
|||
|
<a id="nextmod1" href="Extended6Input.html">6.7. Extended Example: Keyboard Input Listener</a>  »
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
<br />
|
|||
|
|
|||
|
<div class="row jmu-dark-purple-bg">
|
|||
|
<div class="col-md-12">
|
|||
|
<center>
|
|||
|
<a id="contact_us" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="mailto:webmaster@opencsf.org" role="button">Contact Us</a>
|
|||
|
<a id="license" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/lib/license.html" target="_blank">License</a>
|
|||
|
</center>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<script src="_static/js/popper.js-1.14.7-min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
|
|||
|
<script src="_static/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
|||
|
</body>
|
|||
|
</html>
|