565 lines
No EOL
37 KiB
HTML
565 lines
No EOL
37 KiB
HTML
|
||
<!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 — 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"> 1.1. Introduction to Concurrent Systems</a>
|
||
<a class="dropdown-item" href="SysAndModels.html"> 1.2. Systems and Models</a>
|
||
<a class="dropdown-item" href="Themes.html"> 1.3. Themes and Guiding Principles</a>
|
||
<a class="dropdown-item" href="Architectures.html"> 1.4. System Architectures</a>
|
||
<a class="dropdown-item" href="StateModels.html"> 1.5. State Models in UML</a>
|
||
<a class="dropdown-item" href="SequenceModels.html"> 1.6. Sequence Models in UML</a>
|
||
<a class="dropdown-item" href="StateModelImplementation.html"> 1.7. Extended Example: State Model Implementation</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Chapter 2</b></a>
|
||
<a class="dropdown-item" href="ProcessesOverview.html"> 2.1. Processes and OS Basics</a>
|
||
<a class="dropdown-item" href="Multiprogramming.html"> 2.2. Processes and Multiprogramming</a>
|
||
<a class="dropdown-item" href="KernelMechanics.html"> 2.3. Kernel Mechanics</a>
|
||
<a class="dropdown-item" href="Syscall.html"> 2.4. System Call Interface</a>
|
||
<a class="dropdown-item" href="ProcessCycle.html"> 2.5. Process Life Cycle</a>
|
||
<a class="dropdown-item" href="UnixFile.html"> 2.6. The UNIX File Abstraction</a>
|
||
<a class="dropdown-item" href="EventsSignals.html"> 2.7. Events and Signals</a>
|
||
<a class="dropdown-item" href="Extended2Processes.html"> 2.8. Extended Example: Listing Files with Processes</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Chapter 3</b></a>
|
||
<a class="dropdown-item" href="IPCOverview.html"> 3.1. Concurrency with IPC</a>
|
||
<a class="dropdown-item" href="IPCModels.html"> 3.2. IPC Models</a>
|
||
<a class="dropdown-item" href="Pipes.html"> 3.3. Pipes and FIFOs</a>
|
||
<a class="dropdown-item" href="MMap.html"> 3.4. Shared Memory With Memory-mapped Files</a>
|
||
<a class="dropdown-item" href="POSIXvSysV.html"> 3.5. POSIX vs. System V IPC</a>
|
||
<a class="dropdown-item" href="MQueues.html"> 3.6. Message Passing With Message Queues</a>
|
||
<a class="dropdown-item" href="ShMem.html"> 3.7. Shared Memory</a>
|
||
<a class="dropdown-item" href="IPCSems.html"> 3.8. Semaphores</a>
|
||
<a class="dropdown-item" href="Extended3Bash.html"> 3.9. Extended Example: Bash-lite: A Simple Command-line Shell</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Chapter 4</b></a>
|
||
<a class="dropdown-item" href="SocketsOverview.html"> 4.1. Networked Concurrency</a>
|
||
<a class="dropdown-item" href="FiveLayer.html"> 4.2. The TCP/IP Internet Model</a>
|
||
<a class="dropdown-item" href="NetApps.html"> 4.3. Network Applications and Protocols</a>
|
||
<a class="dropdown-item" href="Sockets.html"> 4.4. The Socket Interface</a>
|
||
<a class="dropdown-item" href="TCPSockets.html"> 4.5. TCP Socket Programming: HTTP</a>
|
||
<a class="dropdown-item" href="UDPSockets.html"> 4.6. UDP Socket Programming: DNS</a>
|
||
<a class="dropdown-item" href="AppBroadcast.html"> 4.7. Application-Layer Broadcasting: DHCP</a>
|
||
<a class="dropdown-item" href="Extended4CGI.html"> 4.8. Extended Example: CGI Web Server</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Chapter 5</b></a>
|
||
<a class="dropdown-item" href="InternetOverview.html"> 5.1. The Internet and Connectivity</a>
|
||
<a class="dropdown-item" href="AppLayer.html"> 5.2. Application Layer: Overlay Networks</a>
|
||
<a class="dropdown-item" href="TransLayer.html"> 5.3. Transport Layer</a>
|
||
<a class="dropdown-item" href="NetSec.html"> 5.4. Network Security Fundamentals</a>
|
||
<a class="dropdown-item" href="NetLayer.html"> 5.5. Network Layer: IP</a>
|
||
<a class="dropdown-item" href="LinkLayer.html"> 5.6. Link Layer</a>
|
||
<a class="dropdown-item" href="Wireless.html"> 5.7. Wireless Connectivity: Wi-Fi, Bluetooth, and Zigbee</a>
|
||
<a class="dropdown-item" href="Extended5DNS.html"> 5.8. Extended Example: DNS client</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Chapter 6</b></a>
|
||
<a class="dropdown-item" href="ThreadsOverview.html"> 6.1. Concurrency with Multithreading</a>
|
||
<a class="dropdown-item" href="ProcVThreads.html"> 6.2. Processes vs. Threads</a>
|
||
<a class="dropdown-item" href="RaceConditions.html"> 6.3. Race Conditions and Critical Sections</a>
|
||
<a class="dropdown-item" href="POSIXThreads.html"> 6.4. POSIX Thread Library</a>
|
||
<a class="dropdown-item" href="ThreadArgs.html"> 6.5. Thread Arguments and Return Values</a>
|
||
<a class="dropdown-item" href="ImplicitThreads.html"> 6.6. Implicit Threading and Language-based Threads</a>
|
||
<a class="dropdown-item" href="Extended6Input.html"> 6.7. Extended Example: Keyboard Input Listener</a>
|
||
<a class="dropdown-item" href="Extended6Primes.html"> 6.8. Extended Example: Concurrent Prime Number Search</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Chapter 7</b></a>
|
||
<a class="dropdown-item" href="SynchOverview.html"> 7.1. Synchronization Primitives</a>
|
||
<a class="dropdown-item" href="CritSect.html"> 7.2. Critical Sections and Peterson's Solution</a>
|
||
<a class="dropdown-item" href="Locks.html"> 7.3. Locks</a>
|
||
<a class="dropdown-item" href="Semaphores.html"> 7.4. Semaphores</a>
|
||
<a class="dropdown-item" href="Barriers.html"> 7.5. Barriers</a>
|
||
<a class="dropdown-item" href="Condvars.html"> 7.6. Condition Variables</a>
|
||
<a class="dropdown-item" href="Deadlock.html"> 7.7. Deadlock</a>
|
||
<a class="dropdown-item" href="Extended7Events.html"> 7.8. Extended Example: Event Log File</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Chapter 8</b></a>
|
||
<a class="dropdown-item" href="SynchProblemsOverview.html"> 8.1. Synchronization Patterns and Problems</a>
|
||
<a class="dropdown-item" href="SynchDesign.html"> 8.2. Basic Synchronization Design Patterns</a>
|
||
<a class="dropdown-item" href="ProdCons.html"> 8.3. Producer-Consumer Problem</a>
|
||
<a class="dropdown-item" href="ReadWrite.html"> 8.4. Readers-Writers Problem</a>
|
||
<a class="dropdown-item" href="DiningPhil.html"> 8.5. Dining Philosophers Problem and Deadlock</a>
|
||
<a class="dropdown-item" href="CigSmokers.html"> 8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks</a>
|
||
<a class="dropdown-item" href="Extended8ModExp.html"> 8.7. Extended Example: Parallel Modular Exponentiation</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Chapter 9</b></a>
|
||
<a class="dropdown-item" href="ParallelDistributedOverview.html"> 9.1. Parallel and Distributed Systems</a>
|
||
<a class="dropdown-item" href="ParVConc.html"> 9.2. Parallelism vs. Concurrency</a>
|
||
<a class="dropdown-item" href="ParallelDesign.html"> 9.3. Parallel Design Patterns</a>
|
||
<a class="dropdown-item" href="Scaling.html"> 9.4. Limits of Parallelism and Scaling</a>
|
||
<a class="dropdown-item" href="DistTiming.html"> 9.5. Timing in Distributed Environments</a>
|
||
<a class="dropdown-item" href="DistDataStorage.html"> 9.6. Reliable Data Storage and Location</a>
|
||
<a class="dropdown-item" href="DistConsensus.html"> 9.7. Consensus in Distributed Systems</a>
|
||
<a class="dropdown-item" href="Extended9Blockchain.html"> 9.8. Extended Example: Blockchain Proof-of-Work</a>
|
||
<div class="dropdown-divider"></div>
|
||
<a class="dropdown-item disabled"><b>Appendix A</b></a>
|
||
<a class="dropdown-item" href="CLangOverview.html"> A.1. C Language Reintroduction</a>
|
||
<a class="dropdown-item" href="Debugging.html"> A.2. Documentation and Debugging</a>
|
||
<a class="dropdown-item" href="BasicTypes.html"> A.3. Basic Types and Pointers</a>
|
||
<a class="dropdown-item" href="Arrays.html"> A.4. Arrays, Structs, Enums, and Type Definitions</a>
|
||
<a class="dropdown-item" href="Functions.html"> A.5. Functions and Scope</a>
|
||
<a class="dropdown-item" href="Pointers.html"> A.6. Pointers and Dynamic Allocation</a>
|
||
<a class="dropdown-item" href="Strings.html"> A.7. Strings</a>
|
||
<a class="dropdown-item" href="FunctionPointers.html"> A.8. Function Pointers</a>
|
||
<a class="dropdown-item" href="Files.html"> A.9. Files</a>
|
||
</div>
|
||
</li>
|
||
|
||
|
||
|
||
</ul>
|
||
</div>
|
||
|
||
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
||
<li class="nav-item"><a class="nav-link jmu-gold" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/source/CigSmokers.rst"
|
||
target="_blank" rel="nofollow">Show Source</a></li>
|
||
|
||
</ul>
|
||
</nav>
|
||
|
||
|
||
<div class="container center">
|
||
«  <a id="prevmod" href="DiningPhil.html">8.5. Dining Philosophers Problem and Deadlock</a>
|
||
  ::  
|
||
<a class="uplink" href="index.html">Contents</a>
|
||
  ::  
|
||
<a id="nextmod" href="Extended8ModExp.html">8.7. Extended Example: Parallel Modular Exponentiation</a>  »
|
||
|
||
</div>
|
||
<br />
|
||
|
||
|
||
|
||
<script type="text/javascript" src="_static/js/jquery-2.1.4.min.js"></script>
|
||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||
<script type="text/javascript" src="_static/js/jquery-1.11.4-ui.min.js"></script>
|
||
<script type="text/javascript" src="_static/js/forge-0.7.0.min.js"></script>
|
||
<script type="text/javascript" src="../../../JSAV/lib/jquery.transit.js"></script>
|
||
<script type="text/javascript" src="../../../JSAV/lib/raphael.js"></script>
|
||
<script type="text/javascript" src="../../../JSAV/build/JSAV-min.js"></script>
|
||
<script type="text/javascript" src="_static/js/config.js"></script>
|
||
<script type="text/javascript" src="../../../lib/odsaUtils-min.js"></script>
|
||
<script type="text/javascript" src="../../../lib/odsaMOD-min.js"></script>
|
||
<script type="text/javascript" src="_static/js/d3-4.13.0.min.js"></script>
|
||
<script type="text/javascript" src="_static/js/d3-selection-multi.v1.min.js"></script>
|
||
<script type="text/javascript" src="../../../lib/dataStructures.js"></script>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<div class="container">
|
||
|
||
<script>ODSA.SETTINGS.DISP_MOD_COMP = true;ODSA.SETTINGS.MODULE_NAME = "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 person’s left fork can serve as someone
|
||
else’s 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 />
|
||
SUCCESS<br />sem_wait(paper_sem);<br /> BLOCKED</td>
|
||
<td class="py-0">sem_wait(tobacco_sem);<br />
|
||
SUCCESS<br />sem_wait(match_sem);<br /> BLOCKED</td>
|
||
<td class="py-0">sem_wait(paper_sem);<br />
|
||
BLOCKED<br />sem_wait(tobacco_sem);<br /> 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 />
|
||
SUCCESS<br />sem_wait(match_sem);<br /> BLOCKED</td>
|
||
<td class="py-0">sem_wait(tobacco_sem);<br />
|
||
SUCCESS<br />sem_wait(match_sem);<br /> BLOCKED</td>
|
||
<td class="py-0">sem_wait(paper_sem);<br />
|
||
BLOCKED<br />sem_wait(tobacco_sem);<br /> 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 agent’s 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
|
||
one’s 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&localMode=true&module=CigSmokers&JXOP-debug=true&JOP-lang=en&JXOP-code=java"
|
||
data-frame-width="950"
|
||
data-frame-height="550"
|
||
data-external="false"
|
||
data-points="1.0"
|
||
data-required="True"
|
||
data-showhide="show"
|
||
data-threshold="3"
|
||
data-type="ka"
|
||
data-exer-id="">
|
||
|
||
<div class="center">
|
||
<div id="SynchProbCigSumm_iframe"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<div class="container">
|
||
|
||
<div class="mt-4 container center">
|
||
«  <a id="prevmod1" href="DiningPhil.html">8.5. Dining Philosophers Problem and Deadlock</a>
|
||
  ::  
|
||
<a class="uplink" href="index.html">Contents</a>
|
||
  ::  
|
||
<a id="nextmod1" href="Extended8ModExp.html">8.7. Extended Example: Parallel Modular Exponentiation</a>  »
|
||
</div>
|
||
|
||
|
||
</div>
|
||
|
||
<br />
|
||
|
||
<div class="row jmu-dark-purple-bg">
|
||
<div class="col-md-12">
|
||
<center>
|
||
<a id="contact_us" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="mailto:webmaster@opencsf.org" role="button">Contact Us</a>
|
||
<a id="license" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/lib/license.html" target="_blank">License</a>
|
||
</center>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<script src="_static/js/popper.js-1.14.7-min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
|
||
<script src="_static/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
||
</body>
|
||
</html> |