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

565 lines
No EOL
37 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>8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks &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="7. Extended Example: Parallel Modular Exponentiation" href="Extended8ModExp.html" />
<link rel="prev" title="5. Dining Philosophers Problem and Deadlock" href="DiningPhil.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="CigSmokers.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="CigSmokers.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/CigSmokers.rst"
target="_blank" rel="nofollow">Show Source</a></li>
</ul>
</nav>
<div class="container center">
«&#160;&#160;<a id="prevmod" href="DiningPhil.html">8.5. Dining Philosophers Problem and Deadlock</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod" href="Extended8ModExp.html">8.7. Extended Example: Parallel Modular Exponentiation</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 = "CigSmokers";ODSA.SETTINGS.MODULE_LONG_NAME = "Cigarette Smokers Problem and the Limits of Semaphores and Locks";ODSA.SETTINGS.MODULE_CHAPTER = "Synchronization Patterns and Problems"; ODSA.SETTINGS.BUILD_DATE = "2021-06-01 15:31:51"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script><div class="section" id="cigarette-smokers-problem-and-the-limits-of-semaphores-and-locks">
<h1>8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks<a class="headerlink" href="CigSmokers.html#cigarette-smokers-problem-and-the-limits-of-semaphores-and-locks" title="Permalink to this headline"></a></h1>
<p>One key feature of the dining philosopher problem is that all of the resources
can be treated interchangeably. One persons left fork can serve as someone
elses right fork, and vice versa. In the array of semaphores, the threads could
theoretically wait on the semaphores in a random order and still achieve the
circular wait if circumstances align properly. Consequently, it is tempting to
think that circular wait cannot happen if different types of resources are used.
For instance, is it possible to have deadlock if the resources consist of a
single semaphore, a single lock, and a single condition variable?</p>
<p>The answer to this question is yes; using different types of synchronization
primitives that satisfy the three system properties (mutual exclusion, hold and
wait, no preemption) does not provide safety against deadlock. The
<a class="reference internal" href="Glossary.html#term-cigarette-smokers-problem"><span class="xref std std-term">cigarette smokers problem</span></a> <a class="footnote-reference" href="CigSmokers.html#f46" id="id1">[1]</a> helps to illustrate this point, but
it actually proves a stronger point as well. While the dining philosophers
problem could be solved by using an additional semaphore, the cigarette smokers
problem highlights a scenario that is provably impossible to solve with semaphores alone.</p>
<p>The scenario for the cigarette smokers problem consists of four threads: three
smokers and one agent. In order to smoke, the smoker needs to acquire three
items: tobacco, paper, and a match. Once the smoker has all three, they combine
the paper and tobacco to roll a cigarette and use the match to light it. Each of
the three smokers has an infinite supply of exactly one item and needs the other
two. <a class="reference external" href="CigSmokers.html#cl8-29">Code Listing 8.29</a> shows a sample outline for the smoker
threads. The smoker shown there is assumed to have an infinite supply of tobacco
but needs the match and paper. The smoker sends a signal to request more paper
and matches when they are finished smoking. The other two threads are similar,
but one would wait on semaphores for a match and tobacco and the third would
wait on tobacco and paper.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl8-29"><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</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 8.29:</span>
<span class="cm"> Sample structure for a smoker thread</span>
<span class="cm"> */</span>
<span class="kt">void</span> <span class="o">*</span>
<span class="nf">smoker_with_tobacco</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">while</span> <span class="p">(</span><span class="nb">true</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">sem_wait</span> <span class="p">(</span><span class="n">match_sem</span><span class="p">);</span> <span class="cm">/* grab match from table */</span>
<span class="n">sem_wait</span> <span class="p">(</span><span class="n">paper_sem</span><span class="p">);</span> <span class="cm">/* grab paper from table */</span>
<span class="cm">/* roll cigarette and smoke */</span>
<span class="n">sem_post</span> <span class="p">(</span><span class="n">more_needed</span><span class="p">);</span> <span class="cm">/* signal to agent */</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>The fourth thread is an agent that creates two of the three items at a time,
placing the items on the table. Once the items are taken away, the agent waits
on a signal to produce more. <a class="reference external" href="CigSmokers.html#cl8-30">Code Listing 8.30</a> shows an outline of
an agent thread. The agent picks randomly between three cases, producing some
combination of two out of the three items. The agent places the items on the
table, then waits for a request for more items.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl8-30"><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</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 8.30:</span>
<span class="cm"> Sample structure for the agent thread</span>
<span class="cm"> */</span>
<span class="kt">void</span> <span class="o">*</span>
<span class="nf">agent</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">while</span> <span class="p">(</span><span class="nb">true</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">number</span> <span class="o">=</span> <span class="n">rand</span><span class="p">()</span> <span class="o">%</span> <span class="mi">3</span><span class="p">;</span>
<span class="k">switch</span> <span class="p">(</span><span class="n">number</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">case</span> <span class="mi">0</span><span class="o">:</span> <span class="n">sem_post</span> <span class="p">(</span><span class="n">match_sem</span><span class="p">);</span> <span class="cm">/* match and paper */</span>
<span class="n">sem_post</span> <span class="p">(</span><span class="n">paper_sem</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="mi">1</span><span class="o">:</span> <span class="n">sem_post</span> <span class="p">(</span><span class="n">match_sem</span><span class="p">);</span> <span class="cm">/* match and tobacco */</span>
<span class="n">sem_post</span> <span class="p">(</span><span class="n">tobacco_sem</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="mi">2</span><span class="o">:</span> <span class="n">sem_post</span> <span class="p">(</span><span class="n">paper_sem</span><span class="p">);</span> <span class="cm">/* tobacco and paper */</span>
<span class="n">sem_post</span> <span class="p">(</span><span class="n">tobacco_sem</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">sem_wait</span> <span class="p">(</span><span class="n">more_needed</span><span class="p">);</span> <span class="cm">/* wait for request for more */</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>To understand the implications of the cigarette smokers problem, it is important
to emphasize that <a class="reference external" href="CigSmokers.html#cl8-29">Code Listings 8.29</a> and <a class="reference external" href="CigSmokers.html#cl8-30">8.30</a> are just
sample implementations. The <code class="docutils literal notranslate"><span class="pre">smoker_with_tobacco()</span></code> could be changed to wait
on the <code class="docutils literal notranslate"><span class="pre">paper_sem</span></code> before the <code class="docutils literal notranslate"><span class="pre">match_sem</span></code>; the order does not matter.
Similarly, the <code class="docutils literal notranslate"><span class="pre">agent()</span></code> could be written so that case 0 would post to
<code class="docutils literal notranslate"><span class="pre">paper_sem</span></code> before <code class="docutils literal notranslate"><span class="pre">match_sem</span></code>. The result does not rely on any particular
ordering of these lines of code.</p>
<p>In addition to the description above, there is one constraint placed on the
agent thread. Once it is written, it cannot change. The problem is a metaphor
for working with an OS. The agent is the OS, providing a service of some sort;
it is not aware of the design of applications that will be running on the
system. This restriction, then, makes sense. You would not expect your OS to
behave differently whenever you install or update the applications running on it.</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 8.6.1 </p><hr class="mt-1" />
<p>Based on this restriction of the agent thread, the cigarette smokers problem
states that it is <em>impossible</em> to create the smoker threads that would avoid
deadlock. That is, regardless of how you order the calls to <code class="docutils literal notranslate"><span class="pre">sem_wait()</span></code> in
the smoker threads, the possibility of deadlock cannot be avoided. For
instance, consider the outcomes in <a class="reference external" href="CigSmokers.html#tbl8-4">Table 8.4</a> if the agent produces
a match and tobacco. If these items are grabbed by two threads, no smoker can progress.</p>
<center>
<table class="table table-bordered">
<thead class="thead-light">
<tr>
<th class="py-0 center">Smoker with Tobacco</th>
<th class="py-0 center">Smoker with Paper</th>
<th class="py-0 center">Smoker with Match</th>
</tr>
</thead>
<tbody>
<tr>
<td class="py-0">sem_wait(match_sem);<br />&nbsp;&nbsp;
SUCCESS<br />sem_wait(paper_sem);<br />&nbsp;&nbsp; BLOCKED</td>
<td class="py-0">sem_wait(tobacco_sem);<br />&nbsp;&nbsp;
SUCCESS<br />sem_wait(match_sem);<br />&nbsp;&nbsp; BLOCKED</td>
<td class="py-0">sem_wait(paper_sem);<br />&nbsp;&nbsp;
BLOCKED<br />sem_wait(tobacco_sem);<br />&nbsp;&nbsp; BLOCKED</td>
</tr>
</tbody>
</table>
<p>
Table 8.4: Possible scenario when agent places match and tobacco on the table
</p>
</center><p>It is tempting to claim that there is a simple fix: rewrite the
<code class="docutils literal notranslate"><span class="pre">smoker_with_tobacco()</span></code> so that it must wait on the <code class="docutils literal notranslate"><span class="pre">paper_sem</span></code> before the
<code class="docutils literal notranslate"><span class="pre">match_sem</span></code>. Switching this order would require both
<code class="docutils literal notranslate"><span class="pre">smoker_with_tobacco()</span></code> and <code class="docutils literal notranslate"><span class="pre">smoker_with_match()</span></code> to wait on <code class="docutils literal notranslate"><span class="pre">paper_sem</span></code>
first. Since the agent had only incremented the <code class="docutils literal notranslate"><span class="pre">tobacco_sem</span></code> and
<code class="docutils literal notranslate"><span class="pre">match_sem</span></code>, the <code class="docutils literal notranslate"><span class="pre">smoker_with_paper()</span></code> could proceed without being blocked.
While that would be the case in this situation, consider the next round where
the agent places a different combination on the table. If that combination
included paper and tobacco, the <code class="docutils literal notranslate"><span class="pre">smoker_with_tobacco()</span></code> could, once again,
push the system into deadlock as in <a class="reference external" href="CigSmokers.html#tbl8-5">Table 8.5</a>.</p>
<center>
<table class="table table-bordered">
<thead class="thead-light">
<tr>
<th class="py-0 center">Smoker with Tobacco</th>
<th class="py-0 center">Smoker with Paper</th>
<th class="py-0 center">Smoker with Match</th>
</tr>
</thead>
<tbody>
<tr>
<td class="py-0">sem_wait(paper_sem);<br />&nbsp;&nbsp;
SUCCESS<br />sem_wait(match_sem);<br />&nbsp;&nbsp; BLOCKED</td>
<td class="py-0">sem_wait(tobacco_sem);<br />&nbsp;&nbsp;
SUCCESS<br />sem_wait(match_sem);<br />&nbsp;&nbsp; BLOCKED</td>
<td class="py-0">sem_wait(paper_sem);<br />&nbsp;&nbsp;
BLOCKED<br />sem_wait(tobacco_sem);<br />&nbsp;&nbsp; BLOCKED</td>
</tr>
</tbody>
</table>
<p>
Table 8.5: Imposing a linear ordering does not fix the deadlock
</p>
</center></div>
<div class="section" id="implications-of-the-cigarette-smokers-problem">
<h2>8.6.1. Implications of the Cigarette Smokers Problem<a class="headerlink" href="CigSmokers.html#implications-of-the-cigarette-smokers-problem" title="Permalink to this headline"></a></h2>
<p>The key claim of the cigarette smokers problem is that this scenario has no
solution for traditional semaphores, as they existed at the time. When this
problem was initially proposed, semaphores only provided operations for
incrementing or decrementing their internal value by one. The problem proves
that, if we are limited to those operations only, there are situations in which
avoiding deadlock is provably impossible. Regardless of how the agent and the
smoker threads are constructed, once the agents structure is fixed, any
construction of the smokers will create a possible deadlock situation.</p>
<p>As a result, the cigarette smokers problem proves that some form of
introspection is needed for synchronization primitives. This introspection is
provided by POSIX operations such as <code class="docutils literal notranslate"><span class="pre">sem_try_wait()</span></code> or
<code class="docutils literal notranslate"><span class="pre">pthread_mutex_trylock()</span></code>. These operations provide information about whether
or not the synchronization attempt will succeed. <a class="reference external" href="CigSmokers.html#cl8-31">Code Listing 8.31</a>
illustrates how these forms could be used in a successful solution to the
cigarette smokers problem.</p>
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl8-31"><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">/* Code Listing 8.31:</span>
<span class="cm"> Sample structure for a smoker thread</span>
<span class="cm"> */</span>
<span class="kt">void</span> <span class="o">*</span>
<span class="nf">smoker_with_tobacco</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">while</span> <span class="p">(</span><span class="nb">true</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">sem_wait</span> <span class="p">(</span><span class="n">match_sem</span><span class="p">);</span> <span class="cm">/* grab match from table */</span>
<span class="k">if</span> <span class="p">(</span><span class="n">sem_try_wait</span> <span class="p">(</span><span class="n">paper_sem</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="cm">/* grab paper */</span>
<span class="p">{</span>
<span class="cm">/* roll cigarette and smoke */</span>
<span class="n">sem_post</span> <span class="p">(</span><span class="n">more_needed</span><span class="p">);</span> <span class="cm">/* signal to agent */</span>
<span class="p">}</span>
<span class="k">else</span> <span class="n">sem_post</span> <span class="p">(</span><span class="n">match_sem</span><span class="p">);</span> <span class="cm">/* drop the match */</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
</div>
<div class="section" id="on-cigarette-smokers-and-dining-philosophers">
<h2>8.6.2. On Cigarette Smokers and Dining Philosophers<a class="headerlink" href="CigSmokers.html#on-cigarette-smokers-and-dining-philosophers" title="Permalink to this headline"></a></h2>
<p>The last solution proposed to the dining philosophers problem worked by imposing
a linear ordering on the semaphores. Examining the order of calls to
<code class="docutils literal notranslate"><span class="pre">sem_wait()</span></code> in <a class="reference external" href="CigSmokers.html#tbl8-5">Table 8.5</a>, we can observe that this approach does
not always succeed in avoiding deadlock. Specifically, <a class="reference external" href="CigSmokers.html#tbl8-5">Table 8.5</a> is
built on a solution that imposes an order of <code class="docutils literal notranslate"><span class="pre">paper_sem</span></code> before
<code class="docutils literal notranslate"><span class="pre">tobacco_sem</span></code> and <code class="docutils literal notranslate"><span class="pre">tobacco_sem</span></code> before <code class="docutils literal notranslate"><span class="pre">match_sem</span></code>. By transitivity, this
requires the <code class="docutils literal notranslate"><span class="pre">paper_sem</span></code> before <code class="docutils literal notranslate"><span class="pre">match_sem</span></code>, as implemented in the
<code class="docutils literal notranslate"><span class="pre">smoker_with_tobacco()</span></code>.</p>
<p>It is fair to ask, then, why the linear ordering works for dining philosophers
but fails for cigarette smokers. The key difference has to do with the sum of
the semaphores internal values. In the dining philosophers problem, all
semaphores are initialized to one; consequently, if there are N semaphores,
their sum is also N. In contrast, the cigarette smokers problem initializes all
semaphores to zero. The agent then posts to two out of the three semaphores. The
semaphores are then both decremented and the cycle repeats. As a result, the sum
of the semaphores never reaches three.</p>
<p>Based on these comparisons, we could generalize the cigarette smokers problem to
more than three threads. In this generalized form, there would be N smokers and
the agent would place only N-1 items on the table. If every thread requires two
resources (decrementing two semaphores, acquiring two locks, etc.), then a
linear ordering will not prevent deadlock. The total number of available
resources must be at least the total number of possible requests that can be
made. If there are N threads that can all issue concurrent requests, there must
be N instances available for the linear ordering to prevent deadlock.</p>
<table class="docutils footnote" frame="void" id="f46" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="CigSmokers.html#id1">[1]</a></td><td>The name of this problem illustrates how cultural norms can change
over time. The cigarette smokers problem was first described in a paper in 1971,
when smoking was considered much more socially acceptable than now and rolling
ones own cigarettes was a commonly known practice.</td></tr>
</tbody>
</table>
<div
id="SynchProbCigSumm"
class="embedContainer"
data-exer-name="SynchProbCigSumm"
data-long-name="Cigarette Smokers Summary Questions"
data-short-name="SynchProbCigSumm"
data-frame-src="../../../Exercises/SynchProblems/SynchProbCigSumm.html?selfLoggingEnabled=false&amp;localMode=true&amp;module=CigSmokers&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="SynchProbCigSumm_iframe"></div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="mt-4 container center">
«&#160;&#160;<a id="prevmod1" href="DiningPhil.html">8.5. Dining Philosophers Problem and Deadlock</a>
&#160;&#160;::&#160;&#160;
<a class="uplink" href="index.html">Contents</a>
&#160;&#160;::&#160;&#160;
<a id="nextmod1" href="Extended8ModExp.html">8.7. Extended Example: Parallel Modular Exponentiation</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>