454 lines
No EOL
33 KiB
HTML
454 lines
No EOL
33 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
|
||
|
||
|
||
<html lang="en">
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||
|
||
<title>6.3. Race Conditions and Critical Sections — 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="4. POSIX Thread Library" href="POSIXThreads.html" />
|
||
<link rel="prev" title="2. Processes vs. Threads" href="ProcVThreads.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="RaceConditions.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="RaceConditions.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/RaceConditions.rst"
|
||
target="_blank" rel="nofollow">Show Source</a></li>
|
||
|
||
</ul>
|
||
</nav>
|
||
|
||
|
||
<div class="container center">
|
||
«  <a id="prevmod" href="ProcVThreads.html">6.2. Processes vs. Threads</a>
|
||
  ::  
|
||
<a class="uplink" href="index.html">Contents</a>
|
||
  ::  
|
||
<a id="nextmod" href="POSIXThreads.html">6.4. POSIX Thread Library</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 = "RaceConditions";ODSA.SETTINGS.MODULE_LONG_NAME = "Race Conditions and Critical Sections";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="race-conditions-and-critical-sections">
|
||
<h1>6.3. Race Conditions and Critical Sections<a class="headerlink" href="RaceConditions.html#race-conditions-and-critical-sections" title="Permalink to this headline">¶</a></h1>
|
||
<p><a class="reference internal" href="Glossary.html#term-multithreading"><span class="xref std std-term">Multithreading</span></a> shares some of the basic principles as processes and
|
||
multiprogramming. Specifically, threads are used to achieve <a class="reference internal" href="Glossary.html#term-concurrency"><span class="xref std std-term">concurrent
|
||
execution</span></a> of software. <a class="footnote-reference" href="RaceConditions.html#f40" id="id1">[1]</a> Furthermore, most modern systems
|
||
use kernels that are thread-aware. That is, thread scheduling decisions are
|
||
made by the kernel itself, just as the choice of processes during context
|
||
switches are. Consequently, thread execution is nondeterministic, leading to
|
||
unpredictable timing. As threads in a process share the same virtual memory
|
||
space, this nondeterministic timing can lead to several new types of bugs.</p>
|
||
<div class="section" id="race-conditions">
|
||
<h2>6.3.1. Race Conditions<a class="headerlink" href="RaceConditions.html#race-conditions" title="Permalink to this headline">¶</a></h2>
|
||
<p>A <a class="reference internal" href="Glossary.html#term-race-condition"><span class="xref std std-term">race condition</span></a> is the general term for a bug that arises from the
|
||
nondeterministic timing of execution. If the threads are scheduled in one
|
||
particular order, everything may be fine; however, if there is a slight delay or
|
||
change in the order of scheduling, the process may encounter an error and crash.
|
||
Race conditions can be extremely difficult to debug simply because the bug
|
||
itself depends on the timing of nondeterministic events. It is quite common that
|
||
the bug cannot be recreated by testers, particularly if the problematic timing
|
||
results from a rare circumstance.</p>
|
||
<p>The Therac-25 radiation therapy machine is a classic and well-cited example of a
|
||
race condition with deadly effects. The software for this machine included a
|
||
one-byte counter. If the machine’s operator entered terminal input to the
|
||
machine at the exact moment that the counter overflowed (quite common for a
|
||
counter with only 256 possible values), a critical safety lock failed. This flaw
|
||
made it possible for patients to receive approximately 100 times the intended
|
||
radiation dose, which directly caused the deaths of three patients. <a class="footnote-reference" href="RaceConditions.html#f41" id="id2">[2]</a></p>
|
||
<p>Race conditions with threads can arise from a variety of causes, including (but not limited to):</p>
|
||
<blockquote>
|
||
<div><ul class="simple">
|
||
<li>Two threads try to modify the same global variable at the same time. (See the
|
||
discussion of “Critical Sections” below.)</li>
|
||
<li>Data exists when a thread is created, but becomes invalid when the thread
|
||
tries to access it later. For instance, a thread may be passed a pointer to a
|
||
dynamically allocated data structure; before the thread gets a chance to run
|
||
and retrieve the data, another thread calls <code class="docutils literal notranslate"><span class="pre">free()</span></code> to deallocate the memory on
|
||
the heap.</li>
|
||
<li>A thread returns a pointer to internal variables that were declared within the
|
||
thread’s scope (e.g., a local variable on the thread’s stack). Once the thread
|
||
exits, its stack (and all such variables) are destroyed.</li>
|
||
<li>Multiple threads call the same non-<a class="reference internal" href="Glossary.html#term-thread-safe"><span class="xref std std-term">thread-safe</span></a> function at the same time. (See
|
||
below.)</li>
|
||
</ul>
|
||
</div></blockquote>
|
||
</div>
|
||
<div class="section" id="critical-sections">
|
||
<h2>6.3.2. Critical Sections<a class="headerlink" href="RaceConditions.html#critical-sections" title="Permalink to this headline">¶</a></h2>
|
||
<p>A <a class="reference internal" href="Glossary.html#term-critical-section"><span class="xref std std-term">critical section</span></a> is a sequence of instructions that must be executed
|
||
<a class="reference internal" href="Glossary.html#term-atomic"><span class="xref std std-term">atomically</span></a>. That is, a critical section contains multiple
|
||
instructions that create race conditions if they are <a class="reference internal" href="Glossary.html#term-interleaved"><span class="xref std std-term">interleaved</span></a> with
|
||
other threads. Every access to a global variable in a multithreaded program
|
||
creates a critical section. For instance, consider the single line of C code
|
||
<code class="docutils literal notranslate"><span class="pre">globalvar++;</span></code>, which simply adds 1 to a global variable. In x86 assembly
|
||
language, this single line of code turns into three instructions:</p>
|
||
<div class="highlight-asm border border-dark rounded-lg bg-light px-0 mb-3 notranslate"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0">1
|
||
2
|
||
3</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="nf">movq</span> <span class="no">_globalvar</span><span class="p">(</span><span class="nv">%rip</span><span class="p">),</span> <span class="nv">%rsi</span> <span class="c"># copy from memory into %rsi register</span>
|
||
<span class="no">addq</span> <span class="no">$1</span><span class="p">,</span> <span class="nv">%rsi</span> <span class="c"># increment the value in the register</span>
|
||
<span class="no">movq</span> <span class="nv">%rsi</span><span class="p">,</span> <span class="no">_globalvar</span><span class="p">(</span><span class="nv">%rip</span><span class="p">)</span> <span class="c"># store the result back into memory</span>
|
||
</pre></div>
|
||
</td></tr></table></div>
|
||
<p>To understand how this creates a race condition, assume that the variable
|
||
initially stores the value of 5 and there are two threads (A and B) running. If
|
||
both threads get to this section of code at the same time, a race condition
|
||
arises. Specifically, consider the effects of this order of <em>possible</em> timing:</p>
|
||
<blockquote>
|
||
<div><ul class="simple">
|
||
<li>Thread A executes the first line, copying the current value of <code class="docutils literal notranslate"><span class="pre">globalvar</span></code>
|
||
(5) into the <code class="docutils literal notranslate"><span class="pre">%rsi</span></code> register.</li>
|
||
<li>The kernel triggers a thread switch from A to B. When this occurs, the
|
||
register values get copied into A’s stack.</li>
|
||
<li>Thread B executes all three lines of code. The first line loads the current
|
||
value (5) into %rsi, adds 1 to it, and stores the result (6) back into <code class="docutils literal notranslate"><span class="pre">globalvar</span></code>.</li>
|
||
<li>Thread A resumes some time later, restoring the original value (5) from its
|
||
stack back into the <code class="docutils literal notranslate"><span class="pre">%rsi</span></code> register. A then adds 1 and also stores the result
|
||
(6) back into <code class="docutils literal notranslate"><span class="pre">globalvar</span></code>.</li>
|
||
<li>When another thread tries to get the value of <code class="docutils literal notranslate"><span class="pre">globalvar</span></code> later, its value
|
||
would be 6 even though it was (technically) incremented twice!</li>
|
||
</ul>
|
||
</div></blockquote>
|
||
<p>The key aspect of this example is the timing of the thread switch as the second
|
||
step in this sequence of events. If thread A had been able to execute all three
|
||
instructions without interruption (which is also possible!), the final value
|
||
would be correct. The most frustrating aspect of this situation is that
|
||
re-running the program is unlikely to experience that thread switch in exactly
|
||
the same instant. As such, re-running the program may repeatedly yield the
|
||
correct value of 7 over and over again, giving the programmer the false
|
||
impression that this line of code is behaving correctly. <a class="reference internal" href="Glossary.html#term-synchronization"><span class="xref std std-term">Synchronization</span></a>
|
||
of critical sections is a large and complex topic that will be addressed in its
|
||
own chapter.</p>
|
||
</div>
|
||
<div class="section" id="thread-safety-and-reentrancy">
|
||
<h2>6.3.3. Thread Safety and Reentrancy<a class="headerlink" href="RaceConditions.html#thread-safety-and-reentrancy" title="Permalink to this headline">¶</a></h2>
|
||
<p>A function is considered to be <a class="reference internal" href="Glossary.html#term-thread-safe"><span class="xref std std-term">thread-safe</span></a> if it can be called
|
||
concurrently by multiple threads and produce correct results. For instance, a
|
||
<a class="reference internal" href="Glossary.html#term-mutex"><span class="xref std std-term">mutex</span></a> is a mechanism that can force a sequence of instructions to
|
||
execute in a mutually exclusive (i.e., atomic) manner; in the example above,
|
||
using a mutex with the <code class="docutils literal notranslate"><span class="pre">globalvar</span></code> increment would make the bad interleaving
|
||
impossible. A function is considered to be thread-safe if it can be called by
|
||
multiple threads concurrently without introducing any race conditions.</p>
|
||
<p><a class="reference internal" href="Glossary.html#term-reentrant"><span class="xref std std-term">Reentrancy</span></a> is a closely related concept to thread safety, and the terms
|
||
are sometimes (incorrectly) used interchangeably. The confusion arises because
|
||
reentrant functions tend to be thread safe, and vice versa. However, a reentrant
|
||
function is one that can be interrupted during execution and called again safely
|
||
before the first call is resumed.</p>
|
||
<p>An example of a function that is neither thread-safe nor reentrant is the string
|
||
tokenizer <code class="docutils literal notranslate"><span class="pre">strtok()</span></code>, which takes a string and breaks it into one substring at
|
||
a time based on a specified separator. The problem with <code class="docutils literal notranslate"><span class="pre">strtok()</span></code> is that it
|
||
uses an internal static pointer to keep track of where it needs to continue.
|
||
That is, when <code class="docutils literal notranslate"><span class="pre">strtok()</span></code> returns one a token, the internal pointer is pointing
|
||
to the next token within that particular string. If <code class="docutils literal notranslate"><span class="pre">strtok()</span></code> is interrupted
|
||
and called by another thread, then the internal pointer will be switched to this
|
||
second thread’s string. When the first thread resumes, it will then attempt to
|
||
tokenize the second thread’s string rather than its own.</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-Library.png"><img alt="Decorative C library image" src="_images/CSF-Images-Library.png" style="width: 100%;" /></a>
|
||
</div>
|
||
<p class="topic-title first pt-2 mb-1">C library functions – <string.h></p><hr class="mt-1" />
|
||
<dl class="docutils">
|
||
<dt><code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">*strtok</span> <span class="pre">(char</span> <span class="pre">*restrict</span> <span class="pre">s,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">*restrict</span> <span class="pre">sep);</span></code></dt>
|
||
<dd>Splits a string at instances of the substring <code class="docutils literal notranslate"><span class="pre">sep</span></code>; passing <code class="docutils literal notranslate"><span class="pre">NULL</span></code> as <code class="docutils literal notranslate"><span class="pre">s</span></code> continues with previous string.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">*strtok_r(char</span> <span class="pre">*str,</span> <span class="pre">const</span> <span class="pre">char</span> <span class="pre">*sep,</span> <span class="pre">char</span> <span class="pre">**lasts);</span></code></dt>
|
||
<dd>Reentrant string tokenizer that uses <code class="docutils literal notranslate"><span class="pre">lasts</span></code> to point to the continuation location.</dd>
|
||
</dl>
|
||
</div>
|
||
<p>The main requirements for reentrancy are that a function cannot hold any global
|
||
or static non-constant data, and it cannot call any other non-reentrant
|
||
function. It is still possible for a function to be reentrant but not thread
|
||
safe. For instance, repeatedly using the value of a global variable is acceptable
|
||
with reentrancy; but doing so is not thread safe, as another thread may change
|
||
the value in between uses. On the other hand, a non-reentrant function can be
|
||
made thread-safe by using a mutex to protect any critical sections.</p>
|
||
<p>Ultimately, when writing multithreaded code, programmers must take great care to
|
||
ensure that the functions their threads use are appropriate. Using functions
|
||
that are not thread-safe is an easy way to make debugging extraordinarily
|
||
difficult.</p>
|
||
<table class="docutils footnote" frame="void" id="f40" rules="none">
|
||
<colgroup><col class="label" /><col /></colgroup>
|
||
<tbody valign="top">
|
||
<tr><td class="label"><a class="fn-backref" href="RaceConditions.html#id1">[1]</a></td><td>Early thread implementations were handled solely within the process
|
||
itself, with the thread library enforcing the thread scheduling. This style had
|
||
several disadvantages. First, single- and multi-threaded processes were given
|
||
the same quantum by the scheduler. If a process had 16 threads, each thread
|
||
would be given only 1/16-th of the amount of CPU time as a single-threaded
|
||
process. In fact, the situation was worse than this, as the thread library had
|
||
to inject timed signals to force the switch from one thread to another,
|
||
yielding significant performance overhead. Second, scheduling decisions had to
|
||
be made twice and the code was redundant. In essence, the thread library was
|
||
reproducing kernel code within the user-mode process itself. Consequently, it
|
||
was possible for the library and the kernel to enforce different scheduling
|
||
policies, leading to poor scheduling decisions. Finally, kernel
|
||
thread-awareness is important to gain performance improvements with
|
||
<a class="reference internal" href="Glossary.html#term-multiprocessing"><span class="xref std std-term">multiprocessing</span></a> hardware (including <a class="reference internal" href="Glossary.html#term-multicore"><span class="xref std std-term">multicore</span></a>). Once the kernel
|
||
is aware that a particular process consists of several threads, the kernel can
|
||
schedule multiple threads at the same time for the threads to benefit from
|
||
shared caches. If the kernel is not aware of the threads, it will miss these
|
||
opportunities for potentially considerable speedup.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<table class="docutils footnote" frame="void" id="f41" rules="none">
|
||
<colgroup><col class="label" /><col /></colgroup>
|
||
<tbody valign="top">
|
||
<tr><td class="label"><a class="fn-backref" href="RaceConditions.html#id2">[2]</a></td><td>The Therac-25 story is complicated and there are many lessons that
|
||
should be studied by anyone involved in designing and creating software.
|
||
Another problem with the system is that the software would frequently issue
|
||
warnings based on potential problems. However, these warnings did not shut the
|
||
system down and had no obvious effects or meaning to the operators.
|
||
Consequently, operators learned to ignore all warnings. This behavior is a
|
||
natural response, as the machine would have been entirely unusable if the
|
||
operators had to stop and investigate every warning. In other words, software
|
||
designers should be careful when handling failures and exceptional cases.
|
||
Blaming users for problems that arise is irresponsible and can make bad
|
||
situations significantly worse.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<div
|
||
id="RaceSumm"
|
||
class="embedContainer"
|
||
data-exer-name="RaceSumm"
|
||
data-long-name="Race condition questions"
|
||
data-short-name="RaceSumm"
|
||
data-frame-src="../../../Exercises/Threads/RaceSumm.html?selfLoggingEnabled=false&localMode=true&module=RaceConditions&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="3"
|
||
data-type="ka"
|
||
data-exer-id="">
|
||
|
||
<div class="center">
|
||
<div id="RaceSumm_iframe"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<div class="container">
|
||
|
||
<div class="mt-4 container center">
|
||
«  <a id="prevmod1" href="ProcVThreads.html">6.2. Processes vs. Threads</a>
|
||
  ::  
|
||
<a class="uplink" href="index.html">Contents</a>
|
||
  ::  
|
||
<a id="nextmod1" href="POSIXThreads.html">6.4. POSIX Thread Library</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> |