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

602 lines
No EOL
40 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>7.7. Deadlock &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="8. Extended Example: Event Log File" href="Extended7Events.html" />
<link rel="prev" title="6. Condition Variables" href="Condvars.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="Deadlock.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="Deadlock.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/Deadlock.rst"
target="_blank" rel="nofollow">Show Source</a></li>
</ul>
</nav>
<div class="container center">
«&#160;&#160;<a id="prevmod" href="Condvars.html">7.6. Condition Variables</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod" href="Extended7Events.html">7.8. Extended Example: Event Log File</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 = "Deadlock";ODSA.SETTINGS.MODULE_LONG_NAME = "Deadlock";ODSA.SETTINGS.MODULE_CHAPTER = "Synchronization Primitives"; 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="id1">
<h1>7.7. Deadlock<a class="headerlink" href="Deadlock.html#id1" title="Permalink to this headline"></a></h1>
<p>The <a class="reference internal" href="Glossary.html#term-synchronization-primitive"><span class="xref std std-term">synchronization primitives</span></a> described in
this chapter provide flexible mechanisms to solve many problems related to the
timing of concurrent threads. These mechanisms can enforce mutually exclusive
access to <a class="reference internal" href="Glossary.html#term-critical-section"><span class="xref std std-term">critical sections</span></a>, they can send signals of
custom events, they can require a minimum number of threads reach a common
point, and so on. However, there are common pitfalls and errors that can arise
from their use. One problem (described in the section on locks) is making the
critical section the wrong size, introducing slow performance. But that is a
minor problem in comparison to <a class="reference internal" href="Glossary.html#term-deadlock"><span class="xref std std-term">deadlock</span></a>.</p>
<p>Deadlock is the <strong>permanent and unresolvable blocking</strong> of two or more threads
that results from each waiting on the other. It is important to note that
deadlock is different from <a class="reference internal" href="Glossary.html#term-starvation"><span class="xref std std-term">starvation</span></a>, where a thread may have to wait
for a long time. For instance, consider a thread that repeatedly tries to lock a
mutex; when it fails, it goes to sleep for a while and tries again. Now, assume
this thread is very unlucky and it fails every time. This thread is <em>not</em>
experiencing deadlock; it is experiencing starvation. The difference is that,
with starvation, it is <em>possible</em> that the thread might get lucky in the future.
With deadlock, there is no possibility.</p>
<p><a class="reference external" href="Deadlock.html#cl7-18">Code Listing 7.18</a> provides a simple illustration of how deadlock
can happen. There are two threads, running the <code class="docutils literal notranslate"><span class="pre">first()</span></code> and <code class="docutils literal notranslate"><span class="pre">second()</span></code>
functions. The code for <code class="docutils literal notranslate"><span class="pre">first()</span></code> tries to acquire semaphore <code class="docutils literal notranslate"><span class="pre">sem_a</span></code> before
<code class="docutils literal notranslate"><span class="pre">sem_b</span></code>, while <code class="docutils literal notranslate"><span class="pre">second()</span></code> acquires them in the opposite order.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl7-18"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 7.18:</span>
<span class="cm"> Code that is likely to lead to deadlock</span>
<span class="cm"> */</span>
<span class="cm">/* struct contains shared semaphores */</span>
<span class="k">struct</span> <span class="n">args</span> <span class="p">{</span>
<span class="n">sem_t</span> <span class="n">sem_a</span><span class="p">;</span>
<span class="n">sem_t</span> <span class="n">sem_b</span><span class="p">;</span>
<span class="p">};</span>
<span class="kt">void</span> <span class="o">*</span>
<span class="nf">first</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span> <span class="n">_args</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">struct</span> <span class="n">args</span> <span class="o">*</span><span class="n">args</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">args</span> <span class="o">*</span><span class="p">)</span> <span class="n">_args</span><span class="p">;</span>
<span class="cm">/* Acquire &quot;sem_a&quot; before &quot;sem_b&quot; */</span>
<span class="n">sem_wait</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">sem_a</span><span class="p">);</span>
<span class="n">sem_wait</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">sem_b</span><span class="p">);</span>
<span class="cm">/* other code here */</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="o">*</span>
<span class="nf">second</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span> <span class="n">_args</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">struct</span> <span class="n">args</span> <span class="o">*</span><span class="n">args</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">args</span> <span class="o">*</span><span class="p">)</span> <span class="n">_args</span><span class="p">;</span>
<span class="cm">/* Acquire &quot;sem_b&quot; before &quot;sem_a&quot; */</span>
<span class="n">sem_wait</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">sem_b</span><span class="p">);</span>
<span class="n">sem_wait</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">sem_a</span><span class="p">);</span>
<span class="cm">/* other code here */</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>The problem arises if there is a thread switch after one of the threads
successfully acquires the first semaphore it needs. That is, assume that
<code class="docutils literal notranslate"><span class="pre">first()</span></code> runs and acquires <code class="docutils literal notranslate"><span class="pre">sem_a</span></code>, then a thread switch occurs. At that
point, <code class="docutils literal notranslate"><span class="pre">second()</span></code> starts running and acquires <code class="docutils literal notranslate"><span class="pre">sem_b</span></code>. But <code class="docutils literal notranslate"><span class="pre">second()</span></code> gets
blocked when it tries to acquire <code class="docutils literal notranslate"><span class="pre">sem_a</span></code>, which is held by <code class="docutils literal notranslate"><span class="pre">first()</span></code>. At
that point, the system switches back to <code class="docutils literal notranslate"><span class="pre">first()</span></code>, which gets blocked trying
to acquire <code class="docutils literal notranslate"><span class="pre">sem_b</span></code>. At this point, both threads are waiting on each other
permanently.</p>
<p>It is important to emphasize that code like that shown in <a class="reference external" href="Deadlock.html#cl7-18">Code Listing 7.18</a> does not guarantee that deadlock occurs. This fact becomes clear
when you consider <a href="Deadlock.html#deadlockstate">Figure 7.7.1</a>, which shows the state
model for this code. Once <code class="docutils literal notranslate"><span class="pre">first()</span></code> acquires <code class="docutils literal notranslate"><span class="pre">sem_a</span></code>, the emergence of
deadlock depends on <code class="docutils literal notranslate"><span class="pre">second()</span></code> waiting on <code class="docutils literal notranslate"><span class="pre">sem_b</span></code> before <code class="docutils literal notranslate"><span class="pre">first()</span></code> does.
If the order is different, the system could return back to the state in which
neither semaphore is acquired.</p>
<div class="figure mb-2 align-center" id="id4">
<span id="deadlockstate"></span><a class="reference internal image-reference" href="_images/CSF-Images.7.3.png"><img class="p-3 mb-2 align-center border border-dark rounded-lg" alt="State model for Code Listing 7.18" src="_images/CSF-Images.7.3.png" style="width: 80%;" /></a>
<p class="caption align-center px-3"><span class="caption-text"> Figure 7.7.1: State model for Code Listing 7.18</span></p>
</div>
<p>To make the description a little more concrete, imagine that you and a friend
are sitting at a table to eat. There is one pair of chopsticks available; in
order to eat, you need both chopsticks. When the food arrives, you both forget
your manners and try to grab the chopsticks first. You manage to grab one while
your friend got the other. Youre both so hungry that you refuse to let go of
the chopstick you have. But neither of you can eat, because you only have one
chopstick. And since neither of you will give up the one you have, youre
stuck.</p>
<div class="section" id="necessary-conditions">
<h2>7.7.1. Necessary Conditions<a class="headerlink" href="Deadlock.html#necessary-conditions" title="Permalink to this headline"></a></h2>
<p>So what exactly causes deadlock? First, its important to note that deadlock is
a <a class="reference internal" href="Glossary.html#term-race-condition"><span class="xref std std-term">race condition</span></a>. You might write a program that runs millions of times
over the span of years, only avoiding deadlock through lucky timing. As the code
base gets larger and the system gets more complex, the possibility of deadlock
arising gets even worse. For instance, you might have multiple threads that
(without your awareness) use synchronization primitives through layers of
encapsulated code. At some point, the timing of these primitives may line up
precisely to cause deadlock.</p>
<p>There are four necessary conditions that can lead to deadlock. The first three
conditions are generally unavoidable system characteristics. Deadlock could be
made impossible by eliminating a single one of these characteristics.</p>
<blockquote>
<div><ul class="simple">
<li><strong>Mutual exclusion</strong>: Once a resource has been acquired up to its
allowable capacity, no other thread is granted access.</li>
<li><strong>No preemption</strong>: Once a thread has acquired a resource, the
resource cannot be forcibly taken away. For instance, only the owner of a mutex
can unlock it.</li>
<li><strong>Hold and wait</strong>: It is possible that a thread can acquire one
resource and retain ownership of that resource while waiting on another.</li>
</ul>
</div></blockquote>
<p>In modern, general-purpose computing, these three characteristics are <em>de facto</em>
requirements. Violating any of these characteristics would make concurrent
systems development significantly more difficult. For instance, by throwing out
mutual exclusion, <code class="docutils literal notranslate"><span class="pre">pthread_mutex_lock()</span></code> would not block a thread if the mutex
has already been acquired. By eliminating the <em>no preemption</em> characteristic, a
thread would repeatedly need to check if it still holds the mutex or if the
semaphores value is still acceptable.</p>
<p>Eliminating <em>hold and wait</em> would lead to devastating and undesirable
performance. For instance, consider a database with millions of records, each of
which can be locked independently. Once a transaction is ready to commit, the
thread may acquire a single manager lock for the entire database. The reason for
this split design is that manipulating the local record may require several
operations and take a while, but they are independent and can happen in
parallel. The final commit must happen one at a time, but it is very quick.
Eliminating <em>hold and wait</em> would create the worst possible combination. Since
both locks would have to be acquired and released at the same time, it would be
impossible for the records to be manipulated in parallel. At the same time, the
manager lock would have to be held for far too long while a single record is manipulated.</p>
<p>Ultimately, the three characteristics above are unavoidable and undesirable in
modern systems. But its important to note that these three characteristics by
themselves are not sufficient for deadlock. Deadlock is a race condition that
arises by the fourth necessary condition.</p>
<blockquote>
<div><ul class="simple">
<li><strong>Circular wait</strong>: One thread needs a resource held by another, while
this second thread needs a different resource held by the first.</li>
</ul>
</div></blockquote>
<p>Circular wait can be extended for more than two threads intuitively. Thread A
needs something from thread B, which needs something from thread C, which is
waiting on thread A. This chain of dependencies can be made arbitrarily long.
Counterintuitively, circular wait can also arise even if there are multiple
copies of a resource. This is a complex situation that arises in very advanced
types of systems, though, and we refer interested readers to textbooks on OS
design for more information.</p>
<div class="topic border border-dark rounded-lg alert-danger px-2 mb-3">
<div class="figure align-left">
<a class="reference internal image-reference" href="_images/CSF-Images-BugWarning.png"><img alt="Decorative bug warning" src="_images/CSF-Images-BugWarning.png" style="width: 90%;" /></a>
</div>
<p class="topic-title first pt-2 mb-1">Bug Warning</p><hr class="mt-1" />
<p>It is a common mistake to assume that deadlock only arises with certain types of
synchronization primitives, such as mutex locks. This confusion arises because
the term <em>mutual exclusion</em> is often used to mean that only one thread has
access to a critical section. The term is used more broadly here, allowing for
the possibility that there may be multiple concurrent accesses; however, those
accesses are blocking out some others. Ultimately, deadlock can arise with the
use of locks, semaphores, barriers, or condition variables.</p>
</div>
</div>
<div class="section" id="livelock-and-false-solutions">
<h2>7.7.2. Livelock and False Solutions<a class="headerlink" href="Deadlock.html#livelock-and-false-solutions" title="Permalink to this headline"></a></h2>
<p><a class="reference internal" href="Glossary.html#term-livelock"><span class="xref std std-term">Livelock</span></a> is a race condition that is similar to deadlock, though there
is a slight difference. The key distinction with deadlock and livelock is
whether or not the thread is changing state and executing anything. With
deadlock, a thread is blocked and not executing any code; with livelock, the
thread repeatedly changes state between blocked and unblocked, but accomplishes nothing.</p>
<p>As a simple illustration of livelock, consider <a class="reference external" href="Deadlock.html#cl7-19">Code Listing 7.19</a>,
which attempts to fix the deadlock in the example above. In this code, after
successfully acquiring the first semaphore, the threads use <code class="docutils literal notranslate"><span class="pre">sem_try_wait()</span></code>
on the second. If the wait fails (because the semaphore is locked by the other
thread), the thread releases the semaphore it has first acquired and starts over.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl7-19"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 7.19:</span>
<span class="cm"> Livelock occurs when the system is not deadlocked but no work is done</span>
<span class="cm"> */</span>
<span class="kt">void</span> <span class="o">*</span>
<span class="nf">first</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span> <span class="n">_args</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">struct</span> <span class="n">args</span> <span class="o">*</span><span class="n">args</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">args</span> <span class="o">*</span><span class="p">)</span> <span class="n">_args</span><span class="p">;</span>
<span class="cm">/* Acquire &quot;sem_a&quot; before trying to acquire &quot;sem_b&quot; */</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="n">sem_wait</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">sem_a</span><span class="p">);</span>
<span class="cm">/* Now try for the sem_b, breaking out if successful */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">sem_try_wait</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">sem_b</span><span class="p">))</span>
<span class="k">break</span><span class="p">;</span>
<span class="cm">/* Failed to acquire sem_b, so start over */</span>
<span class="n">sem_signal</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">sem_a</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/* other code here */</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="o">*</span>
<span class="nf">second</span> <span class="p">(</span><span class="kt">void</span> <span class="o">*</span> <span class="n">_args</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">struct</span> <span class="n">args</span> <span class="o">*</span><span class="n">args</span> <span class="o">=</span> <span class="p">(</span><span class="k">struct</span> <span class="n">args</span> <span class="o">*</span><span class="p">)</span> <span class="n">_args</span><span class="p">;</span>
<span class="cm">/* Acquire &quot;sem_b&quot; before trying to acquire &quot;sem_a&quot; */</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="n">sem_wait</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">sem_b</span><span class="p">);</span>
<span class="cm">/* Now try for the sem_a, breaking out if successful */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">sem_try_wait</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">sem_a</span><span class="p">))</span>
<span class="k">break</span><span class="p">;</span>
<span class="cm">/* Failed to acquire sem_a, so start over */</span>
<span class="n">sem_signal</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">args</span><span class="o">-&gt;</span><span class="n">sem_b</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/* other code here */</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>This code makes deadlock impossible by voluntarily breaking the characteristic
of hold and wait. Note that it works in this scenario because no work is done
after the first semaphore is acquired. This approach is not generalizable,
though, because most systems will perform work in between the two semaphore
acquisitions; in many instances, that work performed cannot be undone.</p>
<p>While the code avoids deadlock, it still allows for the possibility of livelock.
That is, it is possible that both threads <em>repeatedly</em> are successful when
acquiring the first semaphore, leading to both failing at the second. Then both
threads release the semaphore they hold and start over again. If this keeps
happening, the threads are experiencing livelock. They are not in deadlock
because there is the <em>possibility</em> that a good timing can lead to recovery.
However, unlucky timing is causing the threads to repeatedly block each other,
preventing the system from making progress.</p>
<p>In practice, this code sample is unlikely to experience livelock for a long
time. Specifically, it is very improbable that a thread switch occurs at the
exact same moment repeatedly. But this code structure is a very simple and
special case. As such, this structure is not considered a reliable solution to
avoiding deadlock.</p>
</div>
<div class="section" id="avoiding-deadlock">
<h2>7.7.3. Avoiding Deadlock<a class="headerlink" href="Deadlock.html#avoiding-deadlock" title="Permalink to this headline"></a></h2>
<p>As three of the deadlock conditions (mutual exclusion, no preemption, hold and
wait) are standard features in modern systems, the typical solution to the
avoiding deadlock in software<a class="footnote-reference" href="Deadlock.html#f45" id="id3">[1]</a> is to avoid circular waiting. There are a
variety of strategies that can be employed to avoid circular waiting that can be
applied, depending on the needs of the system being built.</p>
<blockquote>
<div><ul class="simple">
<li>Impose an ordering on resources. If one thread acquires <code class="docutils literal notranslate"><span class="pre">sem_a</span></code> prior to
acquiring <code class="docutils literal notranslate"><span class="pre">sem_b</span></code>, require other threads to follow this order.</li>
<li>Use timed or non-blocking variants that can provide immediate notification of
failure. If a function like <code class="docutils literal notranslate"><span class="pre">pthread_mutex_trylock()</span></code> or
<code class="docutils literal notranslate"><span class="pre">pthread_cond_timedwait()</span></code> returns an error, release other held resources and
try again later.</li>
<li>Limit the number of potential thread accesses. For instance, consider a
scenario where there are five resource instances, and each thread needs two of
them. Using a semaphore initialized to four would guarantee at least one thread
will always have access to both the instances it needs; this strategy allows
that thread to finish its work, eventually releasing both resource instances
for the other threads to use.</li>
<li>Employ higher-level synchronization primitives and strategies. In the next
chapter, we describe some common well-known solutions that are known to be
deadlock-free.</li>
</ul>
</div></blockquote>
<table class="docutils footnote" frame="void" id="f45" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="Deadlock.html#id3">[1]</a></td><td>Advanced systems software, such as OS kernels, use a variety of
techniques for solving the deadlock problem. These include applying the
Bankers algorithm for deadlock avoidance or executing deadlock detection
algorithms that can alert a system administrator. Each approach has its
benefits and drawbacks, and there is no universally accepted solution.</td></tr>
</tbody>
</table>
<div
id="SynchDeadlockSumm"
class="embedContainer"
data-exer-name="SynchDeadlockSumm"
data-long-name="Deadlock questions"
data-short-name="SynchDeadlockSumm"
data-frame-src="../../../Exercises/Synch/SynchDeadlockSumm.html?selfLoggingEnabled=false&amp;localMode=true&amp;module=Deadlock&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="SynchDeadlockSumm_iframe"></div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="mt-4 container center">
«&#160;&#160;<a id="prevmod1" href="Condvars.html">7.6. Condition Variables</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod1" href="Extended7Events.html">7.8. Extended Example: Event Log File</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>