1
0
Fork 0
cl-sites/w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/html/CritSect.html

567 lines
42 KiB
HTML
Raw Normal View History

2025-01-28 10:11:14 +01:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>7.2. Critical Sections and Petersons Solution &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="3. Locks" href="Locks.html" />
<link rel="prev" title="1. Synchronization Primitives" href="SynchOverview.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="CritSect.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="CritSect.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/CritSect.rst"
target="_blank" rel="nofollow">Show Source</a></li>
</ul>
</nav>
<div class="container center">
«&#160;&#160;<a id="prevmod" href="SynchOverview.html">7.1. Synchronization Primitives</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod" href="Locks.html">7.3. Locks</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 = "CritSect";ODSA.SETTINGS.MODULE_LONG_NAME = "Critical Sections and Peterson's Solution";ODSA.SETTINGS.MODULE_CHAPTER = "Synchronization Primitives"; 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="critical-sections-and-peterson-s-solution">
<h1>7.2. Critical Sections and Petersons Solution<a class="headerlink" href="CritSect.html#critical-sections-and-peterson-s-solution" title="Permalink to this headline"></a></h1>
<p><a class="reference internal" href="Glossary.html#term-critical-section"><span class="xref std std-term">Critical sections</span></a> are sequences of instructions that
cannot be interleaved among multiple threads. A simple example of a critical
section arises when two threads share a global variable <code class="docutils literal notranslate"><span class="pre">globalvar</span></code> and both
try to change its value with <code class="docutils literal notranslate"><span class="pre">globalvar++</span></code>. Recall from the <a class="reference external" href="RaceConditions.html">previous chapter</a>
that this line of code compiles into three assembly-language instructions to
load, modify, and store the result.</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>When multiple threads execute this code, a race condition arises since the lines
can be interleaved. For instance, an interrupt during the second instructions
execution could trigger a switch from one thread to another. <a class="reference external" href="CritSect.html#cl7-1">Code Listing 7.1</a>
shows the interleaved sequence of instructions (distinct indentation denotes the
two threads) that would result from this unfortunate timing of the interrupt.</p>
<div class="highlight-asm border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl7-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</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="c"># Code Listing 7.1:</span>
<span class="c"># A possible sequence of assembly language instructions with a race condition</span>
<span class="c"># Thread A copies globalvar (5) into %rsi, adds 1 to it</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="nf">addq</span> <span class="no">$1</span><span class="p">,</span> <span class="nv">%rsi</span>
<span class="c"># Interrupt: Kernel switches to start running thread B</span>
<span class="c"># Thread B begins same code, also loads value of 5 into %rsi</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="nf">addq</span> <span class="no">$1</span><span class="p">,</span> <span class="nv">%rsi</span>
<span class="nf">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"># Thread B has copied 6 back into globalvar in memory</span>
<span class="c"># Kernel later switches back to thread A</span>
<span class="c"># Thread A also copies 6 back into globalvar</span>
<span class="nf">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>
</pre></div>
</td></tr></table></div>
<p>The result of this interleaving, assuming <code class="docutils literal notranslate"><span class="pre">globalvar</span></code> was originally 5, is
that the threads (together) performed <code class="docutils literal notranslate"><span class="pre">globalvar++</span></code> twice, but the value only
gets changed to 6 instead of the correct value of 7. The problem is that an
interrupt occurred before the first thread was able to update <code class="docutils literal notranslate"><span class="pre">globalvar</span></code>,
then the kernel switched to a different thread that read the old value. If this
switch had not occurred until later, then the first thread would have updated
<code class="docutils literal notranslate"><span class="pre">globalvar</span></code> with the value of 6, which is what the second thread would observe
instead of the outdated 5.</p>
<p>It is important to note that the problem isnt the interrupt, per se. If the
interrupt occurs and the kernel switches to <em>any other thread</em>, or if the second
thread were executing a different portion of code that had nothing to do with
<code class="docutils literal notranslate"><span class="pre">globalvar</span></code>, the correct result would be produced. The error arises because of the
combination of the interrupt/switch with the fact that both threads are
accessing the same variable.</p>
<div class="section" id="peterson-s-solution">
<h2>7.2.1. Petersons Solution<a class="headerlink" href="CritSect.html#peterson-s-solution" title="Permalink to this headline"></a></h2>
<p>One approach to solving the problem of critical sections is to employ Petersons
solution, an algorithmic approach that uses shared memory to declare intentions.
<a class="reference external" href="CritSect.html#cl7-2">Code Listing 7.2</a> shows the algorithm, which uses a <code class="docutils literal notranslate"><span class="pre">bool</span></code> array
(<code class="docutils literal notranslate"><span class="pre">flag</span></code>) to signify a threads intent to enter and an <code class="docutils literal notranslate"><span class="pre">int</span></code> variable (<code class="docutils literal notranslate"><span class="pre">turn</span></code>)
to indicate which thread is allowed to enter. <a class="footnote-reference" href="CritSect.html#f42" id="id1">[1]</a></p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl7-2"><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</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 7.2:</span>
<span class="cm"> Peterson&#39;s solution to solving the critical section problem</span>
<span class="cm"> */</span>
<span class="n">flag</span><span class="p">[</span><span class="n">self</span><span class="p">]</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="n">turn</span> <span class="o">=</span> <span class="n">other</span><span class="p">;</span>
<span class="cm">/* busy wait until it is safe to enter */</span>
<span class="k">while</span> <span class="p">(</span><span class="n">flag</span><span class="p">[</span><span class="n">other</span><span class="p">]</span> <span class="o">==</span> <span class="nb">true</span> <span class="o">&amp;&amp;</span> <span class="n">turn</span> <span class="o">==</span> <span class="n">other</span><span class="p">)</span> <span class="p">;</span>
<span class="cm">/* critical section */</span>
<span class="n">flag</span><span class="p">[</span><span class="n">self</span><span class="p">]</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
</pre></div>
</td></tr></table></div>
<p>The <code class="docutils literal notranslate"><span class="pre">turn</span></code> variable plays a critical role in ensuring the correct functioning
of the solution. Specifically, this variable makes threads adopt a <em>polite</em>
approach to requesting access: when a thread wants to enter the critical
section, it must declare that the other thread gets to go first. Since this type
of variable manipulation consists of a single write to memory, it can be
considered atomic. Consequently, this update does not create a race condition.</p>
<p><a href="CritSect.html#petersonstate">Figure 7.2.1</a> illustrates all possible states and transitions
for Petersons solution. In this model, there are three basic types of events
for each thread: <code class="docutils literal notranslate"><span class="pre">WAIT</span></code>, <code class="docutils literal notranslate"><span class="pre">ENTER</span></code>, and <code class="docutils literal notranslate"><span class="pre">EXIT</span></code>. The six states at the top of
the model show the transitions when there is no contention. For example, from
the left non-critical state (neither are waiting, <code class="docutils literal notranslate"><span class="pre">turn</span></code> = 1), thread 0 could
indicate it attempts to enter the critical section with the <code class="docutils literal notranslate"><span class="pre">WAIT</span></code> event and
immediately enters with the <code class="docutils literal notranslate"><span class="pre">ENTER</span></code> event. The <code class="docutils literal notranslate"><span class="pre">EXIT</span></code> event restores the
system to the non-critical state.</p>
<div class="figure mb-2 align-center" id="id2">
<span id="petersonstate"></span><a class="reference internal image-reference" href="_images/CSF-Images.7.1.png"><img class="p-3 mb-2 align-center border border-dark rounded-lg" alt="State model of Peterson's solution" src="_images/CSF-Images.7.1.png" style="width: 80%;" /></a>
<p class="caption align-center px-3"><span class="caption-text"> Figure 7.2.1: State model of Petersons solution</span></p>
</div>
<p>The four states at the bottom illustrate how the algorithm handles contention.
If neither thread has entered the critical section (states <code class="docutils literal notranslate"><span class="pre">Waiting</span> <span class="pre">0</span></code> and
<code class="docutils literal notranslate"><span class="pre">Waiting</span> <span class="pre">1</span></code>), then the turn variable determines which thread enters. That is,
the condition of the while loop can only resolve to true for one of the threads,
blocking the other from entering. On the other hand, one thread may already be
in the critical section (states <code class="docutils literal notranslate"><span class="pre">Critical</span> <span class="pre">0</span></code> and <code class="docutils literal notranslate"><span class="pre">Critical</span> <span class="pre">1</span></code>) when the
other attempts to enter. In that case, the new thread is forced to wait by the
turn variable. Note that Petersons algorithm can be extended to more than two
threads, as well.</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 7.2.1 </p><hr class="mt-1" />
<p>The state model in <a href="CritSect.html#petersonstate">Figure 7.2.1</a> can be difficult to
trace. Although it would be impractical to provide a full description of all
possible sequences, we can describe a basic trace that traverses through seven
of the states. As before, we use indentation to denote the separate threads,
with thread <code class="docutils literal notranslate"><span class="pre">T0</span></code> unindented and <code class="docutils literal notranslate"><span class="pre">T1</span></code> indented. Comments interspersed
indicate the state and changes to relevant variables.</p>
<div class="highlight-c 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
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Initial state: Non-critical with turn=1 */</span>
<span class="n">flag</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="n">turn</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="cm">/* Change to Waiting 0, turn=1 */</span>
<span class="n">flag</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="n">turn</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="cm">/* Change to Both waiting, turn=0 */</span>
<span class="cm">/* Both are waiting, so turn is the tie-breaker */</span>
<span class="k">while</span> <span class="p">(</span><span class="n">flag</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&amp;&amp;</span> <span class="n">turn</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">;</span> <span class="cm">/* FALSE, turn=0 */</span>
<span class="k">while</span> <span class="p">(</span><span class="n">flag</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&amp;&amp;</span> <span class="n">turn</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">;</span> <span class="cm">/* TRUE, T1 blocked */</span>
<span class="cm">/* Enter Critical 0, Waiting 1</span>
<span class="cm"> Thread 0 does critical work here */</span>
<span class="n">flag</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span> <span class="cm">/* Enter Waiting 1, turn=0 */</span>
<span class="k">while</span> <span class="p">(</span><span class="n">flag</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&amp;&amp;</span> <span class="n">turn</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">;</span> <span class="cm">/* FALSE, flag[0] now false */</span>
<span class="cm">/* Enter Critical 1</span>
<span class="cm"> Thread 1 does critical work here */</span>
<span class="n">flag</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span> <span class="cm">/* Enter Non-critical with turn=0 */</span>
</pre></div>
</td></tr></table></div>
<p>In this trace, both threads begin in non-critical code with neither attempting
to enter a critical section until <code class="docutils literal notranslate"><span class="pre">T0</span></code> executes line 2. <code class="docutils literal notranslate"><span class="pre">T1</span></code> then declares
its intention to enter on line 4. Lines 3 and 5 are the key events to control
the ordering; whichever thread sets turn last loses the rase. Since <code class="docutils literal notranslate"><span class="pre">T1</span></code>
changes turn after <code class="docutils literal notranslate"><span class="pre">T0</span></code> does, <code class="docutils literal notranslate"><span class="pre">T0</span></code> will be the thread to enter the critical
section. To confirm this fact, check the <code class="docutils literal notranslate"><span class="pre">while</span></code>-loop conditions on lines 8
and 9. On these lines, <code class="docutils literal notranslate"><span class="pre">flag[0]</span></code> and <code class="docutils literal notranslate"><span class="pre">flag[1]</span></code> are both true. The condition
then rests exclusively on turn. Later, after <code class="docutils literal notranslate"><span class="pre">T0</span></code> leaves the critical section
(line 13), <code class="docutils literal notranslate"><span class="pre">T1</span></code>s while-loop condition changes because <code class="docutils literal notranslate"><span class="pre">flag[0]</span></code> is now
false; this change allows <code class="docutils literal notranslate"><span class="pre">T1</span></code> to break out of the loop and continue into the
critical section.</p>
</div>
</div>
<div class="section" id="synchronization-properties">
<h2>7.2.2. Synchronization Properties<a class="headerlink" href="CritSect.html#synchronization-properties" title="Permalink to this headline"></a></h2>
<p>Petersons solution provides three desirable properties for solutions to
synchronization problems:</p>
<blockquote>
<div><ul class="simple">
<li><a class="reference internal" href="Glossary.html#term-safety"><span class="xref std std-term">Safety</span></a> There is no way for two threads to be in the critical section
concurrently, so they cannot interfere with each other. This property is also
called <a class="reference internal" href="Glossary.html#term-mutual-exclusion"><span class="xref std std-term">mutual exclusion</span></a>.</li>
<li><a class="reference internal" href="Glossary.html#term-liveness"><span class="xref std std-term">Liveness</span></a> If no thread is in the critical section and at least one tries to
enter, then one of the threads will be able to enter. This property is also
called <a class="reference internal" href="Glossary.html#term-progress"><span class="xref std std-term">progress</span></a>.</li>
<li><a class="reference internal" href="Glossary.html#term-fairness"><span class="xref std std-term">Fairness</span></a> Assuming neither thread can remain in the critical section
indefinitely, if a thread attempts to enter the critical section, it will
eventually do so. This property is also called <a class="reference internal" href="Glossary.html#term-bounded-waiting"><span class="xref std std-term">bounded waiting</span></a>.</li>
</ul>
</div></blockquote>
<p>Examining <a href="CritSect.html#petersonstate">Figure 7.2.1</a> provides informal assurance that
these properties hold. Safety is achieved, because no state allows both threads
to be in the critical section at any time. Liveness is supported by the fact
that all of the waiting states have a transition defined for an <code class="docutils literal notranslate"><span class="pre">ENTER</span></code> event;
liveness could only be broken if the system could get stuck in a waiting state.
Fairness is somewhat more difficult to observe, but arises from the <code class="docutils literal notranslate"><span class="pre">Crit</span> <span class="pre">M</span></code>,
<code class="docutils literal notranslate"><span class="pre">Wait</span> <span class="pre">N</span></code> states in which one thread is in the critical section and the other
is trying to enter. All possible sequences of events from these states must pass
through a state in which the waiting thread gets to enter. Thus, no thread that
tries to enter the critical section can be infinitely blocked from doing so.</p>
<p>The combination of all three of these properties is very difficult to achieve
for synchronization problems. Generally speaking, safety is a requirement and no
approach would be considered a solution without guaranteeing mutually exclusive
access. Liveness is also a standard requirement; approaches that make it
possible to enter a <a class="reference internal" href="Glossary.html#term-deadlock"><span class="xref std std-term">deadlock</span></a> state that blocks all threads from entering
the critical section are also not considered viable solutions.</p>
<p>In contrast, fairness is quite often difficult to achieve in practice and may
even be unnecessary. For instance, consider a system that picks randomly between
threads that are waiting to enter. In addition, assume that each thread will
immediately try to enter the critical section after leaving it. It is
theoretically possible that one thread might be extremely unlucky and never gets
picked. If the choice truly is randomly distributed, this outcome would be as
likely as flipping a coin and getting the same result every time. It is
theoretically possible, but unlikely to happen in practice.</p>
<p>This scenario highlights a key misunderstanding of the liveness property. If
there are no threads in the critical section and one tries to enter, there is no
guarantee that thread will actually be the one allowed in. Rather, without the
fairness property, it may be possible for another thread to come along and enter
without waiting. To illustrate this point, consider the approach shown in
<a class="reference external" href="CritSect.html#cl7-3">Code Listing 7.3</a>. This code meets the safety and liveness properties
by permanently blocking out one of the threads.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl7-3"><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</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 7.3:</span>
<span class="cm"> An approach that guarantees safety and liveness but not fairness </span>
<span class="cm"> */</span>
<span class="k">if</span> <span class="p">(</span><span class="kr">thread</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
<span class="k">while</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">;</span> <span class="cm">/* thread 0 waits infinitely */</span>
<span class="cm">/* enter critical section */</span>
</pre></div>
</td></tr></table></div>
</div>
<div class="section" id="peterson-s-solution-and-modern-hardware">
<h2>7.2.3. Petersons Solution and Modern Hardware<a class="headerlink" href="CritSect.html#peterson-s-solution-and-modern-hardware" title="Permalink to this headline"></a></h2>
<p>The elegance of Petersons solution makes it an interesting approach that
provides these three key properties. However, this approach is generally not
used in modern systems. Petersons solution rests on the assumption that the
instructions are executed in a particular order and memory accesses can be
achieved atomically. Both of these assumptions can fail with modern hardware.
Due to complexities in the design of pipelined CPUs, the instructions may be
executed in a different order. Additionally, if the threads are running on
different cores that do not guarantee immediate cache coherency, the threads may
be using different memory values.</p>
<p>Although there are hardware mechanisms available to overcome these issues,
Petersons solution also suffers from its lack of abstraction. From the systems
programmers perspective, it is more desirable to use abstractions such as
<em>locking</em> and <em>unlocking</em> a critical section rather than setting memory bits. As
such, the remainder of this chapter will focus on higher-level abstractions and
techniques that facilitate more robust and adaptable solutions, called
synchronization primitives, to these types of problems. In general, these
primitives fail to guarantee fairness and thus cannot provide the same
theoretical properties of Petersons solution. However, their higher level of
abstraction provides greater clarity in their practical use.</p>
<table class="docutils footnote" frame="void" id="f42" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="CritSect.html#id1">[1]</a></td><td>The standard explanation of Petersons solution uses 0 and 1 to refer
to the two threads, respectively. Here, we adopt a higher level of abstraction,
using <code class="docutils literal notranslate"><span class="pre">self</span></code> and <code class="docutils literal notranslate"><span class="pre">other</span></code> to refer to the two. For thread 0, <code class="docutils literal notranslate"><span class="pre">self</span></code> would
be 0 and <code class="docutils literal notranslate"><span class="pre">other</span></code> would be 1; the reverse is true for thread 1.</td></tr>
</tbody>
</table>
<div
id="SynchCritSumm"
class="embedContainer"
data-exer-name="SynchCritSumm"
data-long-name="Critical section questions"
data-short-name="SynchCritSumm"
data-frame-src="../../../Exercises/Synch/SynchCritSumm.html?selfLoggingEnabled=false&amp;localMode=true&amp;module=CritSect&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="SynchCritSumm_iframe"></div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="mt-4 container center">
«&#160;&#160;<a id="prevmod1" href="SynchOverview.html">7.1. Synchronization Primitives</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod1" href="Locks.html">7.3. Locks</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>