mirror of
https://github.com/boostorg/thread.git
synced 2026-01-23 18:12:12 +00:00
276 lines
12 KiB
HTML
276 lines
12 KiB
HTML
<html>
|
|
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|
<meta name="keywords" content="threads, BTL, thread library, C++">
|
|
<title>Boost.Threads, Mutex Concept</title>
|
|
</head>
|
|
|
|
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
|
|
|
|
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
|
<tr>
|
|
<td valign="top" width="300">
|
|
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
|
|
</td>
|
|
<td valign="top">
|
|
<h1 align="center">Boost.Threads</h1>
|
|
<h2 align="center">Mutex Concepts</h2>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<hr>
|
|
|
|
<p><a href="#Introduction">Introduction</a><br>
|
|
<a href="#LockingStrategies">Locking Strategies</a><br>
|
|
<a href="#Recursive">Recursive</a><br>
|
|
<a href="#CheckedStrategy">Checked</a><br>
|
|
<a href="#UncheckedStrategy">Unchecked</a><br>
|
|
<a href="#UnspecifiedStrategy">Unspecified</a><br>
|
|
<a href="#SchedulingPolicies">Scheduling Policies</a><br>
|
|
<a href="#FIFO">FIFO</a><br>
|
|
<a href="#Priority Driven">Priority Driven</a><br>
|
|
<a href="#UndefinedScheduling">Undefined</a><br>
|
|
<a href="#UnspecifiedScheduling">Unspecified</a><br>
|
|
<a href="#Requirements">Concept Requirements</a><br>
|
|
<a href="#Mutex">Mutex Concept</a><br>
|
|
<a href="#TryMutex">TryMutex Concept</a><br>
|
|
<a href="#TimedMutex">TimedMutex Concept</a><br>
|
|
<a href="#Models">Models</a></p>
|
|
|
|
<h2><a name="Introduction">Introduction</a></h2>
|
|
|
|
<p>A mutex (short for mutual-exclusion) concept serializes access to
|
|
a resource shared between multiple threads. The <a href="#Mutex">Mutex</a>
|
|
concept, with <a href="#TryMutex">TryMutex</a> and <a href="#TimedMutex">TimedMutex</a>
|
|
refinements, formalize the requirements. A model that implements Mutex and its
|
|
refinements has two states: <b> locked</b> and <b>unlocked</b>. Before using a
|
|
shared resource, a thread locks a Boost.Threads mutex model object,
|
|
insuring <a href="definitions.html#Thread-safe">thread-safe</a> access to the shared
|
|
resource. When use of the shared resource is complete, the thread unlocks the mutex
|
|
model object, allowing another thread to acquire the lock and use the shared resource.</p>
|
|
|
|
<p>Traditional C thread APIs, like Pthreads or the Windows thread APIs, expose
|
|
functions to lock and unlock a mutex model. This is dangerous since it's easy to forget
|
|
to unlock a locked mutex. When the flow of control is complex, with multiple return
|
|
points, the likelihood of forgetting to unlock a mutex model would become even greater.
|
|
When exceptions are thrown, it becomes nearly impossible to ensure that the mutex is
|
|
unlocked properly when using these traditional API's. The result is
|
|
<a href="definitions.html#Deadlock">deadlock</a>.</p>
|
|
|
|
<p>Many C++ threading libraries use a pattern known as <i>Scoped Locking</i>
|
|
<a href="bibliography.html#Schmidt 00">[Schmidt 00]</a> to free the programmer from the
|
|
need to explicitly lock and unlock mutexes. With this pattern, a
|
|
<A href="lock_concept.html">lock concept</A> is employed where the lock model's
|
|
constructor locks the associated mutex model and the destructor automatically does the
|
|
unlocking. The <b>Boost.Threads</b> library takes this pattern to the extreme in that
|
|
lock concepts are the only way to lock and unlock a mutex model: lock and unlock
|
|
functions are not exposed by any <b>Boost.Threads </b>mutex models. This helps to
|
|
ensure safe usage patterns, especially when code throws exceptions.</p>
|
|
|
|
<h2><a name="LockingStrategies">Locking Strategies</a></h2>
|
|
|
|
<p>Every mutex model follows one of several locking strategies. These strategies
|
|
define the semantics for the locking operation when the calling thread already
|
|
owns a lock on the mutex model.</p>
|
|
|
|
<h3><a name="Recursive">Recursive</a></h3>
|
|
|
|
<p>With a recursive locking strategy when a thread attempts to acquire a lock on
|
|
the mutex model for which it already owns a lock, the operation is successful.
|
|
Note the distinction between a thread, which may have multiple locks outstanding
|
|
on a recursive mutex, and a lock object, which even for a recursive mutex cannot
|
|
have its lock() function called multiple times without first calling unlock().</p>
|
|
|
|
<p>Internally a lock count is maintained and the owning thread must unlock the
|
|
mutex model the same number of times that it's locked it before the mutex model's
|
|
state returns to unlocked. Since mutex models in <b>Boost.Threads</b> expose
|
|
locking functionality only through lock concepts, a thread will always unlock a mutex
|
|
model the same number of times that it locked it. This helps to eliminate a whole set
|
|
of errors typically found in traditional C style thread APIs.</p>
|
|
|
|
<p>Classes <A href="recursive_mutex.html">recursive_mutex</A>,
|
|
<A href="recursive_mutex.html">recursive_try_mutex</A> and
|
|
<A href="recursive_mutex.html">recursive_timed_mutex</A> use this locking strategy.</p>
|
|
|
|
<h3><a name="CheckedStrategy">Checked</a></h3>
|
|
|
|
<p>With a checked locking strategy when a thread attempts to acquire a lock on
|
|
the mutex model for which the thread already owns a lock, the operation will fail with
|
|
some sort of error indication. Further, attempts by a thread to unlock a mutex
|
|
that was not locked by the thread will also return some sort of error indication.
|
|
In <b>Boost.Threads</b>, an exception of type <A href="lock_error.html">lock_error</A>
|
|
would be thrown in these cases.</p>
|
|
|
|
<p><b>Boost.Threads</b> does not currently provide any mutex models that use this
|
|
strategy.</p>
|
|
|
|
<h3><a name="UncheckedStrategy">Unchecked</a></h3>
|
|
|
|
<p>With an unchecked locking strategy when a thread attempts to acquire a lock
|
|
on the mutex model for which the thread already owns a lock the operation will
|
|
<a href="definitions.html#Deadlock">deadlock</a>. In general this locking strategy is
|
|
less safe than a checked or recursive strategy, but it's also a faster strategy and so
|
|
is employed by many libraries.</p>
|
|
|
|
<p><b>Boost.Threads</b> does not currently provide any mutex models that use this
|
|
strategy.</p>
|
|
|
|
<h3><a name="UnspecifiedStrategy">Unspecified</a></h3>
|
|
|
|
<p>With an unspecified locking strategy, when a thread attempts to acquire a lock
|
|
on a mutex model for which the thread already owns a lock the operation results in
|
|
<b>undefined behavior</b>. When a mutex model has an unspecified locking strategy the
|
|
programmer must assume that the mutex model instead uses an unchecked strategy.</p>
|
|
|
|
<p>In general a mutex model with an unspecified locking strategy is unsafe, and it
|
|
requires programmer discipline to use the mutex model properly. However, this strategy
|
|
allows an implementation to be as fast as possible with no restrictions on its
|
|
implementation. This is especially true for portable implementations that wrap the
|
|
native threading support of a platform. For this reason, the classes
|
|
<A href="mutex.html">mutex</A>, <A href="mutex.html">try_mutex</A> and
|
|
<A href="mutex.html">timed_mutex</A> use this locking strategy despite the lack of
|
|
safety.</p>
|
|
|
|
<h2><a name="SchedulingPolicies">Scheduling Policies</a></h2>
|
|
|
|
<p>Every mutex model follows one of several scheduling policies. These policies
|
|
define the semantics when the mutex model is unlocked and there is more than one
|
|
thread waiting to acquire a lock. In other words, the policy defines which waiting
|
|
thread shall acquire the lock.</p>
|
|
|
|
<h3><a name="FIFO">FIFO</a></h3>
|
|
|
|
<p>With a FIFO scheduling policy, threads waiting for the lock will acquire it in
|
|
a first come first serve order (or First In First Out). This can help prevent a
|
|
high priority thread from starving lower priority threads that are also waiting
|
|
on the mutex lock.</p>
|
|
|
|
<h3><a name="Priority Driven">Priority Driven</a></h3>
|
|
|
|
<p>With a Priority Driven scheduling policy, the thread with the highest priority
|
|
acquires the lock. Note that this means that low-priority threads may never acquire
|
|
the lock if the mutex model has high contention and there is always at least one
|
|
high-priority thread waiting. This is known as thread starvation. When multiple threads
|
|
of the same priority are waiting on the mutex lock one of the other scheduling
|
|
priorities will determine which thread shall acquire the lock.</p>
|
|
|
|
<h3><a name="UndefinedScheduling">Undefined</a></h3>
|
|
|
|
<p>Threads acquire the lock in no particular order. Users should assume that
|
|
low-priority threads may wait indefinitely, and that threads of the same
|
|
priority acquire the lock in essentially random order.</p>
|
|
|
|
<h3><a name="UnspecifiedScheduling">Unspecified</a></h3>
|
|
|
|
<p>The mutex model does not specify which scheduling policy is used. The programmer
|
|
must assume that an undefined scheduling policy is used. In order to ensure portability,
|
|
all <b>Boost.Threads</b> mutex models use an unspecified scheduling policy.</p>
|
|
|
|
<h2>Concept <a name="Requirements">Requirements</a></h2>
|
|
|
|
<h3><a name="Mutex">Mutex</a> Concept</h3>
|
|
|
|
<p>A Mutex object has two states: locked and unlocked. Mutex object state can only be
|
|
determined by an object meeting the <a href="lock_concept.html#ScopedLock">ScopedLock</a>
|
|
requirements and constructed for the Mutex object.</p>
|
|
|
|
<p>A Mutex is <a href="../../utility/utility.htm#Class noncopyable">noncopyable</a>.</p>
|
|
|
|
<p>For a Mutex type M and an object m of that type, the following expressions must be
|
|
well-formed and have the indicated effects.</p>
|
|
|
|
<table border="1" cellpadding="5">
|
|
<tr>
|
|
<td><b>Expression</b></td>
|
|
<td><b>Effects</b></td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>M m;</code></td>
|
|
<td>Constructs a mutex object m. Post-condition: m is unlocked.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>(&m)->~M();</code></td>
|
|
<td>Precondition: m is unlocked. Destroys a mutex object m.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>M::scoped_lock</code></td>
|
|
<td>A type meeting the <a href="lock_concept.html#ScopedLock">ScopedLock</a>
|
|
requirements.</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<h3><a name="TryMutex">TryMutex</a> Concept</h3>
|
|
<p>A TryMutex must meet the <a href="#Mutex"> Mutex</a> requirements. In addition, for a
|
|
TryMutex type M and an object m of that type, the following expressions must be
|
|
well-formed and have the indicated effects.</p>
|
|
<table border="1" cellpadding="5">
|
|
<tr>
|
|
<td><b>Expression</b></td>
|
|
<td><b>Effects</b></td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>M::scoped_try_lock</code></td>
|
|
<td>A type meeting the <a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a>
|
|
requirements.</td>
|
|
</tr>
|
|
</table>
|
|
<h3><a name="TimedMutex">TimedMutex</a> Concept</h3>
|
|
<p>A TimedMutex must meet the <a href="#TryMutex"> TryMutex</a> requirements. In addition, for a
|
|
TimedMutex type M and an object m of that type, the following
|
|
expressions must be well-formed and have the indicated effects.</p>
|
|
<table border="1" cellpadding="5">
|
|
<tr>
|
|
<td><b>Expression</b></td>
|
|
<td><b>Effects</b></td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>M::scoped_timed_lock</code></td>
|
|
<td>A type meeting the <a href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a>
|
|
requirements.</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<h2><a name="Models">Models</a></h2>
|
|
|
|
<p> <b>Boost.Threads</b> currently supplies six classes which model mutex
|
|
concepts.</p>
|
|
|
|
<table border="1" cellpadding="5">
|
|
<tr>
|
|
<td><b>Concept</b></td>
|
|
<td><b>Refines</b></td>
|
|
<td><b>Classes Modeling the Concept</b></td>
|
|
</tr>
|
|
<tr>
|
|
<td valign="top"><a href="#Mutex">Mutex</a></td>
|
|
<td valign="top"> </td>
|
|
<td><A href="mutex.html">mutex</A><br>
|
|
<A href="recursive_mutex.html">recursive_mutex</A></td>
|
|
</tr>
|
|
<tr>
|
|
<td valign="top"><a href="#TryMutex">TryMutex</a></td>
|
|
<td valign="top"><a href="#Mutex">Mutex</a></td>
|
|
<td><A href="mutex.html">try_mutex<br>
|
|
</A><A href="recursive_mutex.html">recursive_try_mutex</A> </td>
|
|
</tr>
|
|
<tr>
|
|
<td valign="top"><a href="#TimedMutex">TimedMutex</a></td>
|
|
<td valign="top"><a href="#TryMutex">TryMutex</a></td>
|
|
<td><A href="mutex.html">timed_mutex<br>
|
|
</A><A href="recursive_mutex.html">recursive_timed_mutex</A></td>
|
|
</tr>
|
|
</table>
|
|
|
|
<hr>
|
|
|
|
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->03 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39333" -->
|
|
</p>
|
|
|
|
<p><i>© Copyright <A href="mailto:williamkempf@hotmail.com">William E. Kempf</A>
|
|
2001 all rights reserved.</i></p>
|
|
|
|
</body>
|
|
</html>
|