573 lines
37 KiB
HTML
573 lines
37 KiB
HTML
|
|
|||
|
<!DOCTYPE html>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<html lang="en">
|
|||
|
<head>
|
|||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|||
|
|
|||
|
<title>6.2. Processes vs. 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="3. Race Conditions and Critical Sections" href="RaceConditions.html" />
|
|||
|
<link rel="prev" title="1. Concurrency with Multithreading" href="ThreadsOverview.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="ProcVThreads.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="ProcVThreads.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/ProcVThreads.rst"
|
|||
|
target="_blank" rel="nofollow">Show Source</a></li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</nav>
|
|||
|
|
|||
|
|
|||
|
<div class="container center">
|
|||
|
«  <a id="prevmod" href="ThreadsOverview.html">6.1. Concurrency with Multithreading</a>
|
|||
|
  ::  
|
|||
|
<a class="uplink" href="index.html">Contents</a>
|
|||
|
  ::  
|
|||
|
<a id="nextmod" href="RaceConditions.html">6.3. Race Conditions and Critical Sections</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 = "ProcVThreads";ODSA.SETTINGS.MODULE_LONG_NAME = "Processes vs. Threads";ODSA.SETTINGS.MODULE_CHAPTER = "Concurrency with Multithreading"; ODSA.SETTINGS.BUILD_DATE = "2021-06-14 17:15:25"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script><div class="section" id="processes-vs-threads">
|
|||
|
<h1>6.2. Processes vs. Threads<a class="headerlink" href="ProcVThreads.html#processes-vs-threads" title="Permalink to this headline">¶</a></h1>
|
|||
|
<p>Recall from <a class="reference external" href="ProcessesOverview.html">Processes and OS Basics</a> that a <a class="reference internal" href="Glossary.html#term-process"><span class="xref std std-term">process</span></a>
|
|||
|
is fundamentally defined by having a unique virtual memory space. The process
|
|||
|
contains a code segment that consists of the executable machine-language
|
|||
|
instructions, while the statically allocated global variables are stored in the
|
|||
|
data segment. The heap and stack segments contain the dynamically allocated data
|
|||
|
and local variables for this execution of the program.</p>
|
|||
|
<p>Every process begins by executing the instructions contained in <code class="docutils literal notranslate"><span class="pre">main()</span></code>. The
|
|||
|
<code class="docutils literal notranslate"><span class="pre">%pc</span></code> register defines the flow of the code by pointing to the next
|
|||
|
instruction to be executed. The call instruction can modify the control flow by
|
|||
|
jumping to other functions. When this happens, the return address (and other
|
|||
|
related information) is placed on the stack to maintain the program’s logical
|
|||
|
flow. This single, logical sequence of executing instructions within a process
|
|||
|
is known as a <em>thread of execution</em>, which we typically just call a <a class="reference internal" href="Glossary.html#term-thread"><span class="xref std std-term">thread</span></a>.</p>
|
|||
|
<div class="section" id="multithreading">
|
|||
|
<h2>6.2.1. Multithreading<a class="headerlink" href="ProcVThreads.html#multithreading" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p><a class="reference internal" href="Glossary.html#term-multithreading"><span class="xref std std-term">Multithreaded</span></a> processes have multiple threads that perform tasks
|
|||
|
concurrently. Just like the thread that runs the code in <code class="docutils literal notranslate"><span class="pre">main()</span></code>, additional
|
|||
|
threads each use a function as an entry point. To maintain the logical flow of
|
|||
|
these additional threads, each thread is assigned a separate stack. However, all
|
|||
|
of the other segments of memory, including the code, global data, heap, and
|
|||
|
kernel, are shared.</p>
|
|||
|
<p>Another way to consider the relationship between threads and processes is to
|
|||
|
separate the system functions of <a class="reference internal" href="Glossary.html#term-scheduling"><span class="xref std std-term">scheduling</span></a> and <em>resource
|
|||
|
ownership</em>. Switching from one thread to another would change the system from
|
|||
|
working toward one computational goal to working toward another. This means that
|
|||
|
the purpose of switching between threads is to create a schedule that controls
|
|||
|
when each thread is running on the CPU.</p>
|
|||
|
<p>On the other hand, processes act as containers for resource ownership. As the
|
|||
|
process runs, it may request access to files stored on the disk, open network
|
|||
|
connections, or request the creation of a new window on the desktop. All of
|
|||
|
these resources are allocated to the process, not individual threads.</p>
|
|||
|
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl6-1"><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</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 6.1:</span>
|
|||
|
<span class="cm"> Structure of a simple multithreaded program framework</span>
|
|||
|
<span class="cm"> */</span>
|
|||
|
|
|||
|
<span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp"></span>
|
|||
|
<span class="cm">/* Include thread libraries */</span>
|
|||
|
|
|||
|
<span class="kt">int</span> <span class="n">number</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
|
|||
|
|
|||
|
<span class="kt">void</span> <span class="o">*</span>
|
|||
|
<span class="nf">thread_A</span> <span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">args</span><span class="p">)</span>
|
|||
|
<span class="p">{</span>
|
|||
|
<span class="kt">int</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
|
|||
|
<span class="n">printf</span> <span class="p">(</span><span class="s">"A: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">x</span> <span class="o">+</span> <span class="n">number</span><span class="p">);</span>
|
|||
|
<span class="cm">/* Exit thread */</span>
|
|||
|
<span class="p">}</span>
|
|||
|
|
|||
|
<span class="kt">void</span> <span class="o">*</span>
|
|||
|
<span class="nf">thread_B</span> <span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">args</span><span class="p">)</span>
|
|||
|
<span class="p">{</span>
|
|||
|
<span class="kt">int</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
|
|||
|
<span class="n">printf</span> <span class="p">(</span><span class="s">"B: %d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">y</span> <span class="o">+</span> <span class="n">number</span><span class="p">);</span>
|
|||
|
<span class="cm">/* Exit thread */</span>
|
|||
|
<span class="p">}</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">/* Create thread A */</span>
|
|||
|
<span class="cm">/* Create thread B */</span>
|
|||
|
<span class="cm">/* Wait for threads to finish */</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><a class="reference external" href="ProcVThreads.html#cl6-1">Code Listing 6.1</a> shows the structure of a simple program that creates two
|
|||
|
threads that run concurrently. For now, comments are used to indicate where the
|
|||
|
thread management code would be written. Thread A declares a local variable
|
|||
|
<code class="docutils literal notranslate"><span class="pre">x</span></code> and prints out the message A: 8, which is the sum of the value of <code class="docutils literal notranslate"><span class="pre">x</span></code>
|
|||
|
(5) and the global variable <code class="docutils literal notranslate"><span class="pre">number</span></code> (3). Thread B declares <code class="docutils literal notranslate"><span class="pre">y</span></code> and prints
|
|||
|
out B: 5, for similar reasons. One observation about this sample is that the
|
|||
|
code for the threads looks like normal functions in a typical program. The
|
|||
|
difference only becomes apparent when we run the program.</p>
|
|||
|
<p>When the program is run, the scheduling that controls when the threads run is
|
|||
|
<a class="reference internal" href="Glossary.html#term-nondeterminism"><span class="xref std std-term">nondeterministic</span></a> from the programmer’s perspective. By looking at the
|
|||
|
code, we can conclude that line 13 runs before line 14, just like line 21 runs
|
|||
|
before line 22. However, we cannot predict the ordering between line 13 and line
|
|||
|
21. This choice is made at run-time and is controlled by the kernel. When
|
|||
|
looking at source code for multithreaded programs, we assume the lines of code
|
|||
|
are <a class="reference internal" href="Glossary.html#term-interleaved"><span class="xref std std-term">interleaved</span></a>, meaning that the kernel can switch back and forth
|
|||
|
whenever it chooses to do so.</p>
|
|||
|
<div class="topic border border-dark rounded-lg bg-light px-2 mb-3">
|
|||
|
<div class="figure align-left">
|
|||
|
<a class="reference internal image-reference" href="_images/CSF-Images-Example.png"><img alt="Decorative example icon" src="_images/CSF-Images-Example.png" style="width: 100%;" /></a>
|
|||
|
</div>
|
|||
|
<p class="topic-title first pt-2 mb-1">Example 6.2.1 </p><hr class="mt-1" />
|
|||
|
<p><a class="reference external" href="ProcVThreads.html#tbl6-1">Table 6.1</a> shows three of the possible interleavings of <a class="reference external" href="ProcVThreads.html#cl6-1">Code Listing 6.1</a>. In each
|
|||
|
of these cases, the indentation is used to indicate which thread performs an
|
|||
|
action (thread A is not indented and thread B is). In interleaving 1, thread A
|
|||
|
runs to completion before thread B starts. In interleaving 2, thread B sets the
|
|||
|
value of y before thread A prints its message. <strong>Note that this timing is not
|
|||
|
observed without a debugger, since setting y produces no visible result.</strong>
|
|||
|
Finally, in interleaving 3, thread B’s print statement occurs before thread A’s.</p>
|
|||
|
<center>
|
|||
|
<div class="col-md-10">
|
|||
|
<table class="table table-bordered">
|
|||
|
<thead class="jmu-dark-purple-bg text-light">
|
|||
|
<tr>
|
|||
|
<th class="py-0 center" style="width: 33%">Interleaving 1</th>
|
|||
|
<th class="py-0 center" style="width: 33%">Interleaving 2</th>
|
|||
|
<th class="py-0 center" style="width: 33%">Interleaving 3</th>
|
|||
|
</tr>
|
|||
|
</thead>
|
|||
|
<tbody class="bg-white">
|
|||
|
<tr>
|
|||
|
<td class="py-0"><code>x = 5<br />print "A:8"<br /> y = 2<br /> print "B:7"</code></td>
|
|||
|
<td class="py-0"><code>x = 5<br /> y = 2<br />print "A:8"<br /> print "B:7"</code></td>
|
|||
|
<td class="py-0"><code> y = 2<br />x = 5<br /> print "B:7"<br />print "A:8"</code></td>
|
|||
|
</tr>
|
|||
|
</tbody>
|
|||
|
</table>
|
|||
|
</div>
|
|||
|
<div class="col-md-8 center">
|
|||
|
Table 6.1: Three possible interleavings of Code Listing 6.1
|
|||
|
</div>
|
|||
|
<br /></div>
|
|||
|
<p>More interleavings are possible than those shown in <a class="reference external" href="ProcVThreads.html#tbl6-1">Table 6.1</a>. The
|
|||
|
only requirement is that the order of instructions <strong>within a single thread</strong>
|
|||
|
must match the order specified in the code. The selection of which thread has an
|
|||
|
instruction run is seemingly randomized.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="advantages-and-disadvantages-of-threads">
|
|||
|
<h2>6.2.2. Advantages and Disadvantages of Threads<a class="headerlink" href="ProcVThreads.html#advantages-and-disadvantages-of-threads" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>Using multiple threads offers a number of advantages over creating an
|
|||
|
application from multiple processes. First, using multiple threads helps
|
|||
|
programmers build modularity into their code more effectively. Complex software,
|
|||
|
especially the types of applications built with object-oriented programming,
|
|||
|
typically involves modular components that interact with each other. Oftentimes,
|
|||
|
the program can run more efficiently if these components can run concurrently
|
|||
|
without performing context switches. Threads provide a foundation for this
|
|||
|
programming goal.</p>
|
|||
|
<p>One common example of using threads for different purposes is an interactive
|
|||
|
graphical user interface. Application programmers build in keyboard or mouse
|
|||
|
listeners that are responsible for detecting and responding to key presses,
|
|||
|
mouse clicks, and other such events. These types of event listeners are simply
|
|||
|
concurrent threads within the process. By implementing the listener behavior in
|
|||
|
a separate thread, the programmer can simplify the structure of the program.</p>
|
|||
|
<p>Threads also require significantly less overhead for switching and for
|
|||
|
communicating. A process context switch requires changing the system’s current
|
|||
|
view of virtual memory, which is a time-consuming operation. Switching from one
|
|||
|
thread to another is a lot faster. For two processes to exchange data, they have
|
|||
|
to initiate <a class="reference internal" href="Glossary.html#term-interprocess-communication"><span class="xref std std-term">interprocess communication (IPC)</span></a>, which requires asking the kernel for help. IPC generally
|
|||
|
involves performing at least one context switch. Since all threads in a process
|
|||
|
share the heap, data, and code, there is no need to get the kernel involved. The
|
|||
|
threads can communicate directly by reading and writing global variables.</p>
|
|||
|
<p>At the same time, the lack of isolation between threads in a single process can
|
|||
|
also lead to some disadvantages. If one thread crashes due to a segmentation
|
|||
|
fault or other error, all other threads and the entire process are killed. This
|
|||
|
situation can lead to data and system corruption if the other threads were in
|
|||
|
the middle of some important task.</p>
|
|||
|
<p>As an example, assume that the application is a server program with one thread
|
|||
|
responsible for logging all requests and a separate thread for handling the
|
|||
|
requests. If the request handler thread crashes before the logging thread has a
|
|||
|
chance to write the request to its log file, there would be no record of the
|
|||
|
request. The system administrators left to determine what went wrong would have
|
|||
|
no information about the request, so they may waste a lot of time validating
|
|||
|
other requests that were all good.</p>
|
|||
|
<p>The lack of isolation between threads also creates a new type of programming
|
|||
|
bugs called <a class="reference internal" href="Glossary.html#term-race-condition"><span class="xref std std-term">race conditions</span></a>. In a race condition, the
|
|||
|
behavior of the program depends on the timing of the thread scheduling. One
|
|||
|
example of a race condition is when two threads both try to change the value of
|
|||
|
a global variable. The final value of the global variable would depend on which
|
|||
|
thread set the value last.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="thread-models">
|
|||
|
<h2>6.2.3. Thread Models<a class="headerlink" href="ProcVThreads.html#thread-models" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>Throughout this chapter, we will be focusing on the POSIX thread model, which is
|
|||
|
independent of language and OS (though mostly associated with UNIX-like OS). The
|
|||
|
POSIX specification defines a thread as a <em>single flow of control within a
|
|||
|
process.</em> Based on this definition, all threads within a process exist in a
|
|||
|
single address space; as such, all threads in a process can access anything
|
|||
|
stored in memory if the address can be determined. On the other hand, each
|
|||
|
thread has a unique copy of certain pieces of data that are required for
|
|||
|
execution; these unique copies include the <code class="docutils literal notranslate"><span class="pre">errno</span></code> variable (used for
|
|||
|
detecting errors that occur in C standard library functions), general purpose
|
|||
|
registers, and a stack pointer. <a class="reference external" href="ProcVThreads.html#tbl6-2">Table 6.2</a> summarizes what the POSIX
|
|||
|
specificat declares is unique per thread and what is accessible to all threads.</p>
|
|||
|
<center>
|
|||
|
<div class="col-md-10 center">
|
|||
|
<table class="table table-bordered">
|
|||
|
<thead class="jmu-dark-purple-bg text-light">
|
|||
|
<tr>
|
|||
|
<th class="py-0 center">Unique per thread</th>
|
|||
|
<th class="py-0 center">Accessible by all threads in process</th>
|
|||
|
</tr>
|
|||
|
</thead>
|
|||
|
<tbody class="text-left">
|
|||
|
<tr>
|
|||
|
<td class="py-0">
|
|||
|
<ul>
|
|||
|
<li>Thread ID</li>
|
|||
|
<li>Scheduling priority and policies</li>
|
|||
|
<li><code>errno</code> value</li>
|
|||
|
<li>Floating point environment</li>
|
|||
|
<li>Thread-specific key/value bindings</li>
|
|||
|
<li>Resources required for control flow</li>
|
|||
|
</ul>
|
|||
|
</td>
|
|||
|
<td class="py-0">
|
|||
|
<ul>
|
|||
|
<li>Static variables</li>
|
|||
|
<li>Storage obtained by <code>malloc()</code></li>
|
|||
|
<li>Directly addressable storage</li>
|
|||
|
<li>Automatic variables</li>
|
|||
|
</ul>
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
</tbody>
|
|||
|
</table>
|
|||
|
</div>
|
|||
|
<div class="col-md-10 center">
|
|||
|
Table 6.2: Data that is unique to or shared between POSIX threads
|
|||
|
</div>
|
|||
|
</center>
|
|||
|
<br /><p>In typical implementations, scheduling of POSIX threads is typically performed
|
|||
|
by the kernel. This approach allows the kernel to make scheduling decisions
|
|||
|
consistently across processes, while also making context switches between
|
|||
|
threads efficient (as the virtual memory image does not change). The POSIX model
|
|||
|
is not the only way to structure and organize threads. There are other models
|
|||
|
that have been used for multithreading in a variety of systems.</p>
|
|||
|
<p>Early versions of Java used the <a class="reference internal" href="Glossary.html#term-green-threads"><span class="xref std std-term">Green threads</span></a> model (named for the Green
|
|||
|
Team inside the Sun Microsystems that implemented the library). In this model,
|
|||
|
the Java virtual machine (JVM), which ran as a single process, is responsible
|
|||
|
for scheduling between threads in an application. The kernel underlying the JVM
|
|||
|
had no awareness of the presence of multiple threads. An advantage of this
|
|||
|
approach is that switching between threads is efficient, as there are no system
|
|||
|
calls that require the intervention of the kernel. However, all threads had to
|
|||
|
subdivide the process’s given CPU time; as the number of threads increased,
|
|||
|
performance would dramatically decrease, as each thread would get less and less CPU time.</p>
|
|||
|
<p>Solaris and other forms of System V UNIX adopted a model known as
|
|||
|
<a class="reference internal" href="Glossary.html#term-light-weight-process"><span class="xref std std-term">light-weight processes (LWPs)</span></a>. In this model,
|
|||
|
multiple LWPs within a single process execute on top of a single kernel thread.
|
|||
|
Like the Green threads model, scheduling between LWPs is handled by a user-mode
|
|||
|
thread library rather than the kernel. However, unlike Green threads, the LWP
|
|||
|
model allows a single process to run on top of multiple kernel threads. This
|
|||
|
approach creates a many-to-many relationship between user- and kernel-mode
|
|||
|
threads. Consequently, processes with several LWPs could distribute their
|
|||
|
execution time across multiple kernel threads for more CPU time.</p>
|
|||
|
<p>Windows and the .NET framework use a <a class="reference internal" href="Glossary.html#term-fiber"><span class="xref std std-term">fiber</span></a> model, which is similar to
|
|||
|
the POSIX model. Like a POSIX thread, fibers share a single address space and
|
|||
|
each fiber is mapped to a single kernel thread. The primary difference is that
|
|||
|
fibers within a single process use cooperative multitasking. This approach
|
|||
|
offers a significant advantage for ensuring safe access to resources shared
|
|||
|
between the threads, as the fibers have greater control over when switches
|
|||
|
occur.</p>
|
|||
|
<p><a href="ProcVThreads.html#thrmodel">Figure 6.2.2</a> summarizes how the four threading models map user
|
|||
|
threads to kernel threads. In all cases but Green threads, we assume that the
|
|||
|
process consists of three kernel threads that can be scheduled independently.
|
|||
|
The POSIX threads and fibers form a 1:1 model from user threads to kernel
|
|||
|
threads, with the primary difference being the intervention of the fiber
|
|||
|
scheduler. The Green threads model forms an N:1 relationship, as the kernel is
|
|||
|
not aware of the multiple threads running on top of the JVM. The LWP model is
|
|||
|
described as M:N because there is no direct link between the number of user and
|
|||
|
kernel threads. For each of the N kernel threads, there is a virtual CPU, and
|
|||
|
the LWP library dynamically maps the M user threads to these virtual CPUs
|
|||
|
according to its own scheduling policies.</p>
|
|||
|
<div class="figure mb-2 align-center" id="id3" style="width: 100%">
|
|||
|
<span id="thrmodel"></span><a class="reference internal image-reference" href="_images/CSF-Images.6.1.png"><img class="p-3 mb-2 align-center border border-dark rounded-lg" alt="Mapping models for POSIX, Green threads, fibers, and lightweight processes" src="_images/CSF-Images.6.1.png" style="width: 90%;" /></a>
|
|||
|
<p class="caption align-center px-3"><span class="caption-text"> Figure 6.2.2: Mapping models for POSIX, Green threads, fibers, and lightweight processes</span></p>
|
|||
|
</div>
|
|||
|
<div
|
|||
|
id="ProcVThreadsSumm"
|
|||
|
class="embedContainer"
|
|||
|
data-exer-name="ProcVThreadsSumm"
|
|||
|
data-long-name="Threads vs. processes questions"
|
|||
|
data-short-name="ProcVThreadsSumm"
|
|||
|
data-frame-src="../../../Exercises/Threads/ProcVThreadsSumm.html?selfLoggingEnabled=false&localMode=true&module=ProcVThreads&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="ProcVThreadsSumm_iframe"></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="container">
|
|||
|
|
|||
|
<div class="mt-4 container center">
|
|||
|
«  <a id="prevmod1" href="ThreadsOverview.html">6.1. Concurrency with Multithreading</a>
|
|||
|
  ::  
|
|||
|
<a class="uplink" href="index.html">Contents</a>
|
|||
|
  ::  
|
|||
|
<a id="nextmod1" href="RaceConditions.html">6.3. Race Conditions and Critical Sections</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>
|