1
0
Fork 0
cl-sites/w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/html/RaceConditions.html
2025-01-28 10:11:14 +01:00

454 lines
No EOL
33 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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 &mdash; 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">&nbsp;&nbsp;&nbsp;1.1. Introduction to Concurrent Systems</a>
<a class="dropdown-item" href="SysAndModels.html">&nbsp;&nbsp;&nbsp;1.2. Systems and Models</a>
<a class="dropdown-item" href="Themes.html">&nbsp;&nbsp;&nbsp;1.3. Themes and Guiding Principles</a>
<a class="dropdown-item" href="Architectures.html">&nbsp;&nbsp;&nbsp;1.4. System Architectures</a>
<a class="dropdown-item" href="StateModels.html">&nbsp;&nbsp;&nbsp;1.5. State Models in UML</a>
<a class="dropdown-item" href="SequenceModels.html">&nbsp;&nbsp;&nbsp;1.6. Sequence Models in UML</a>
<a class="dropdown-item" href="StateModelImplementation.html">&nbsp;&nbsp;&nbsp;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">&nbsp;&nbsp;&nbsp;2.1. Processes and OS Basics</a>
<a class="dropdown-item" href="Multiprogramming.html">&nbsp;&nbsp;&nbsp;2.2. Processes and Multiprogramming</a>
<a class="dropdown-item" href="KernelMechanics.html">&nbsp;&nbsp;&nbsp;2.3. Kernel Mechanics</a>
<a class="dropdown-item" href="Syscall.html">&nbsp;&nbsp;&nbsp;2.4. System Call Interface</a>
<a class="dropdown-item" href="ProcessCycle.html">&nbsp;&nbsp;&nbsp;2.5. Process Life Cycle</a>
<a class="dropdown-item" href="UnixFile.html">&nbsp;&nbsp;&nbsp;2.6. The UNIX File Abstraction</a>
<a class="dropdown-item" href="EventsSignals.html">&nbsp;&nbsp;&nbsp;2.7. Events and Signals</a>
<a class="dropdown-item" href="Extended2Processes.html">&nbsp;&nbsp;&nbsp;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">&nbsp;&nbsp;&nbsp;3.1. Concurrency with IPC</a>
<a class="dropdown-item" href="IPCModels.html">&nbsp;&nbsp;&nbsp;3.2. IPC Models</a>
<a class="dropdown-item" href="Pipes.html">&nbsp;&nbsp;&nbsp;3.3. Pipes and FIFOs</a>
<a class="dropdown-item" href="MMap.html">&nbsp;&nbsp;&nbsp;3.4. Shared Memory With Memory-mapped Files</a>
<a class="dropdown-item" href="POSIXvSysV.html">&nbsp;&nbsp;&nbsp;3.5. POSIX vs. System V IPC</a>
<a class="dropdown-item" href="MQueues.html">&nbsp;&nbsp;&nbsp;3.6. Message Passing With Message Queues</a>
<a class="dropdown-item" href="ShMem.html">&nbsp;&nbsp;&nbsp;3.7. Shared Memory</a>
<a class="dropdown-item" href="IPCSems.html">&nbsp;&nbsp;&nbsp;3.8. Semaphores</a>
<a class="dropdown-item" href="Extended3Bash.html">&nbsp;&nbsp;&nbsp;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">&nbsp;&nbsp;&nbsp;4.1. Networked Concurrency</a>
<a class="dropdown-item" href="FiveLayer.html">&nbsp;&nbsp;&nbsp;4.2. The TCP/IP Internet Model</a>
<a class="dropdown-item" href="NetApps.html">&nbsp;&nbsp;&nbsp;4.3. Network Applications and Protocols</a>
<a class="dropdown-item" href="Sockets.html">&nbsp;&nbsp;&nbsp;4.4. The Socket Interface</a>
<a class="dropdown-item" href="TCPSockets.html">&nbsp;&nbsp;&nbsp;4.5. TCP Socket Programming: HTTP</a>
<a class="dropdown-item" href="UDPSockets.html">&nbsp;&nbsp;&nbsp;4.6. UDP Socket Programming: DNS</a>
<a class="dropdown-item" href="AppBroadcast.html">&nbsp;&nbsp;&nbsp;4.7. Application-Layer Broadcasting: DHCP</a>
<a class="dropdown-item" href="Extended4CGI.html">&nbsp;&nbsp;&nbsp;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">&nbsp;&nbsp;&nbsp;5.1. The Internet and Connectivity</a>
<a class="dropdown-item" href="AppLayer.html">&nbsp;&nbsp;&nbsp;5.2. Application Layer: Overlay Networks</a>
<a class="dropdown-item" href="TransLayer.html">&nbsp;&nbsp;&nbsp;5.3. Transport Layer</a>
<a class="dropdown-item" href="NetSec.html">&nbsp;&nbsp;&nbsp;5.4. Network Security Fundamentals</a>
<a class="dropdown-item" href="NetLayer.html">&nbsp;&nbsp;&nbsp;5.5. Network Layer: IP</a>
<a class="dropdown-item" href="LinkLayer.html">&nbsp;&nbsp;&nbsp;5.6. Link Layer</a>
<a class="dropdown-item" href="Wireless.html">&nbsp;&nbsp;&nbsp;5.7. Wireless Connectivity: Wi-Fi, Bluetooth, and Zigbee</a>
<a class="dropdown-item" href="Extended5DNS.html">&nbsp;&nbsp;&nbsp;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">&nbsp;&nbsp;&nbsp;6.1. Concurrency with Multithreading</a>
<a class="dropdown-item" href="ProcVThreads.html">&nbsp;&nbsp;&nbsp;6.2. Processes vs. Threads</a>
<a class="dropdown-item" href="RaceConditions.html">&nbsp;&nbsp;&nbsp;6.3. Race Conditions and Critical Sections</a>
<a class="dropdown-item" href="POSIXThreads.html">&nbsp;&nbsp;&nbsp;6.4. POSIX Thread Library</a>
<a class="dropdown-item" href="ThreadArgs.html">&nbsp;&nbsp;&nbsp;6.5. Thread Arguments and Return Values</a>
<a class="dropdown-item" href="ImplicitThreads.html">&nbsp;&nbsp;&nbsp;6.6. Implicit Threading and Language-based Threads</a>
<a class="dropdown-item" href="Extended6Input.html">&nbsp;&nbsp;&nbsp;6.7. Extended Example: Keyboard Input Listener</a>
<a class="dropdown-item" href="Extended6Primes.html">&nbsp;&nbsp;&nbsp;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">&nbsp;&nbsp;&nbsp;7.1. Synchronization Primitives</a>
<a class="dropdown-item" href="CritSect.html">&nbsp;&nbsp;&nbsp;7.2. Critical Sections and Peterson's Solution</a>
<a class="dropdown-item" href="Locks.html">&nbsp;&nbsp;&nbsp;7.3. Locks</a>
<a class="dropdown-item" href="Semaphores.html">&nbsp;&nbsp;&nbsp;7.4. Semaphores</a>
<a class="dropdown-item" href="Barriers.html">&nbsp;&nbsp;&nbsp;7.5. Barriers</a>
<a class="dropdown-item" href="Condvars.html">&nbsp;&nbsp;&nbsp;7.6. Condition Variables</a>
<a class="dropdown-item" href="Deadlock.html">&nbsp;&nbsp;&nbsp;7.7. Deadlock</a>
<a class="dropdown-item" href="Extended7Events.html">&nbsp;&nbsp;&nbsp;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">&nbsp;&nbsp;&nbsp;8.1. Synchronization Patterns and Problems</a>
<a class="dropdown-item" href="SynchDesign.html">&nbsp;&nbsp;&nbsp;8.2. Basic Synchronization Design Patterns</a>
<a class="dropdown-item" href="ProdCons.html">&nbsp;&nbsp;&nbsp;8.3. Producer-Consumer Problem</a>
<a class="dropdown-item" href="ReadWrite.html">&nbsp;&nbsp;&nbsp;8.4. Readers-Writers Problem</a>
<a class="dropdown-item" href="DiningPhil.html">&nbsp;&nbsp;&nbsp;8.5. Dining Philosophers Problem and Deadlock</a>
<a class="dropdown-item" href="CigSmokers.html">&nbsp;&nbsp;&nbsp;8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks</a>
<a class="dropdown-item" href="Extended8ModExp.html">&nbsp;&nbsp;&nbsp;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">&nbsp;&nbsp;&nbsp;9.1. Parallel and Distributed Systems</a>
<a class="dropdown-item" href="ParVConc.html">&nbsp;&nbsp;&nbsp;9.2. Parallelism vs. Concurrency</a>
<a class="dropdown-item" href="ParallelDesign.html">&nbsp;&nbsp;&nbsp;9.3. Parallel Design Patterns</a>
<a class="dropdown-item" href="Scaling.html">&nbsp;&nbsp;&nbsp;9.4. Limits of Parallelism and Scaling</a>
<a class="dropdown-item" href="DistTiming.html">&nbsp;&nbsp;&nbsp;9.5. Timing in Distributed Environments</a>
<a class="dropdown-item" href="DistDataStorage.html">&nbsp;&nbsp;&nbsp;9.6. Reliable Data Storage and Location</a>
<a class="dropdown-item" href="DistConsensus.html">&nbsp;&nbsp;&nbsp;9.7. Consensus in Distributed Systems</a>
<a class="dropdown-item" href="Extended9Blockchain.html">&nbsp;&nbsp;&nbsp;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">&nbsp;&nbsp;&nbsp;A.1. C Language Reintroduction</a>
<a class="dropdown-item" href="Debugging.html">&nbsp;&nbsp;&nbsp;A.2. Documentation and Debugging</a>
<a class="dropdown-item" href="BasicTypes.html">&nbsp;&nbsp;&nbsp;A.3. Basic Types and Pointers</a>
<a class="dropdown-item" href="Arrays.html">&nbsp;&nbsp;&nbsp;A.4. Arrays, Structs, Enums, and Type Definitions</a>
<a class="dropdown-item" href="Functions.html">&nbsp;&nbsp;&nbsp;A.5. Functions and Scope</a>
<a class="dropdown-item" href="Pointers.html">&nbsp;&nbsp;&nbsp;A.6. Pointers and Dynamic Allocation</a>
<a class="dropdown-item" href="Strings.html">&nbsp;&nbsp;&nbsp;A.7. Strings</a>
<a class="dropdown-item" href="FunctionPointers.html">&nbsp;&nbsp;&nbsp;A.8. Function Pointers</a>
<a class="dropdown-item" href="Files.html">&nbsp;&nbsp;&nbsp;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">
«&#160;&#160;<a id="prevmod" href="ProcVThreads.html">6.2. Processes vs. Threads</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod" href="POSIXThreads.html">6.4. POSIX Thread Library</a>&#160;&#160;»
</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 machines 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
threads scope (e.g., a local variable on the threads 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 As 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 threads string. When the first thread resumes, it will then attempt to
tokenize the second threads 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 &lt;string.h&gt;</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&amp;localMode=true&amp;module=RaceConditions&amp;JXOP-debug=true&amp;JOP-lang=en&amp;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">
«&#160;&#160;<a id="prevmod1" href="ProcVThreads.html">6.2. Processes vs. Threads</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod1" href="POSIXThreads.html">6.4. POSIX Thread Library</a>&#160;&#160;»
</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>