264 lines
18 KiB
HTML
264 lines
18 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh" dir="ltr" class="client-nojs" xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh">
|
|
<head><meta http-equiv="x-ua-compatible" content="ie=edge">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
<title>std::shared_mutex</title>
|
|
<link rel="stylesheet" href="ext.css" />
|
|
<link rel="stylesheet" href="site_modules.css" />
|
|
</head>
|
|
<body class="mediawiki ltr sitedir-ltr ns-0 ns-subject page-cpp_thread_shared_mutex skin-cppreference2 action-view cpp-navbar">
|
|
<div id="cpp-content-base">
|
|
<div id="content"><a id="top"></a>
|
|
<h1 id="firstHeading" class="firstHeading"><span style="font-size:0.7em; line-height:130%">std::</span>shared_mutex</h1>
|
|
<div id="bodyContent">
|
|
<div id="contentSub"><span class="subpages">< <a href="cpp.html">cpp</a>‎ | <a href="cpp-thread.html">thread</a></span></div>
|
|
<div id="mw-content-text" lang="zh" dir="ltr" class="mw-content-ltr" xml:lang="zh">
|
|
<table class="t-dcl-begin">
|
|
<tbody>
|
|
<tr class="t-dsc-header">
|
|
<td>
|
|
<div>定义于头文件 <code><a href="cpp-header-shared_mutex.html"><shared_mutex></a></code></div>
|
|
</td>
|
|
<td></td>
|
|
<td></td>
|
|
</tr>
|
|
<tr class="t-dcl t-since-cxx17">
|
|
<td>
|
|
<div><span class="mw-geshi cpp source-cpp"><span class="kw1">class</span> shared_mutex<span class="sy4">;</span></span></div>
|
|
</td>
|
|
<td class="t-dcl-nopad"></td>
|
|
<td><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></td>
|
|
</tr>
|
|
<tr class="t-dcl-sep">
|
|
<td></td>
|
|
<td></td>
|
|
<td></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<p><code>shared_mutex</code> 类是一个同步原语,可用于保护共享数据不被多个线程同时访问。与便于独占访问的其他互斥类型不同,shared_mutex 拥有二个访问级别:</p>
|
|
<ul>
|
|
<li><i>共享</i> - 多个线程能共享同一互斥的所有权。</li>
|
|
</ul>
|
|
<ul>
|
|
<li><i>独占性</i> - 仅一个线程能占有互斥。</li>
|
|
</ul>
|
|
<p>若一个线程已获取<i>独占性</i>锁(通过 <span class="t-lc"><a href="cpp-thread-shared_mutex-lock.html">lock</a></span> 、 <span class="t-lc"><a href="cpp-thread-shared_mutex-try_lock.html">try_lock</a></span> ),则无其他线程能获取该锁(包括<i>共享</i>的)。</p>
|
|
<p>仅当任何线程均未获取<i>独占性</i>锁时,<i>共享</i>锁能被多个线程获取(通过 <span class="t-lc"><a href="cpp-thread-shared_mutex-lock_shared.html">lock_shared</a></span> 、 <span class="t-lc"><a href="cpp-thread-shared_mutex-try_lock_shared.html">try_lock_shared</a></span> )。</p>
|
|
<p>在一个线程内,同一时刻只能获取一个锁(<i>共享</i>或<i>独占性</i>)。</p>
|
|
<p>共享互斥体在能由任何数量的线程同时读共享数据,但一个线程只能在无其他线程同时读写时写同一数据时特别有用。</p>
|
|
<p><code>shared_mutex</code> 类满足<a href="cpp-named_req-SharedMutex.html"><span style="font-style:italic">共享互斥体</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(SharedMutex)</span></a> 和<a href="cpp-named_req-StandardLayoutType.html"><span style="font-style:italic">标准布局类型</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(StandardLayoutType)</span></a> 的所有要求。</p>
|
|
<h3><span class="mw-headline" id=".E6.88.90.E5.91.98.E7.B1.BB.E5.9E.8B">成员类型</span></h3>
|
|
<table class="t-dsc-begin">
|
|
<tr class="t-dsc-hitem">
|
|
<td>成员类型</td>
|
|
<td>定义</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><code>native_handle_type</code><span class="t-mark">(可选)</span></td>
|
|
<td><i>实现定义</i></td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E6.88.90.E5.91.98.E5.87.BD.E6.95.B0">成员函数</span></h3>
|
|
<table class="t-dsc-begin">
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div t-dsc-member-nobold-div">
|
|
<div><a href="cpp-thread-shared_mutex-shared_mutex.html"><span class="t-lines"><span>(构造函数)</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>构造互斥<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div t-dsc-member-nobold-div">
|
|
<div><a href="cpp-thread-shared_mutex-~shared_mutex.html"><span class="t-lines"><span>(析构函数)</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>销毁互斥<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><span class="t-lines"><span>operator=</span></span></div>
|
|
<div><span class="t-lines"><span><span class="t-cmark">[被删除]</span></span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>不可复制赋值<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="2">
|
|
<h5><span class="mw-headline" id=".E6.8E.92.E4.BB.96.E6.80.A7.E9.94.81.E5.AE.9A">排他性锁定</span></h5>
|
|
</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-thread-shared_mutex-lock.html"><span class="t-lines"><span>lock</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>锁定互斥,若互斥不可用则阻塞<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-thread-shared_mutex-try_lock.html"><span class="t-lines"><span>try_lock</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>尝试锁定互斥,若互斥不可用则返回<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-thread-shared_mutex-unlock.html"><span class="t-lines"><span>unlock</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>解锁互斥<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="2">
|
|
<h5><span class="mw-headline" id=".E5.85.B1.E4.BA.AB.E9.94.81.E5.AE.9A">共享锁定</span></h5>
|
|
</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-thread-shared_mutex-lock_shared.html"><span class="t-lines"><span>lock_shared</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>为共享所有权锁定互斥,若互斥不可用则阻塞<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-thread-shared_mutex-try_lock_shared.html"><span class="t-lines"><span>try_lock_shared</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>尝试为共享所有权锁定互斥,若互斥不可用则返回<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-thread-shared_mutex-unlock_shared.html"><span class="t-lines"><span>unlock_shared</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>解锁互斥(共享所有权)<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="2">
|
|
<h5><span class="mw-headline" id=".E5.8E.9F.E7.94.9F.E5.8F.A5.E6.9F.84">原生句柄</span></h5>
|
|
</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-thread-shared_mutex-native_handle.html"><span class="t-lines"><span>native_handle</span></span></a></div>
|
|
</div>
|
|
</td>
|
|
<td>返回底层实现定义的原生句柄<br />
|
|
<span class="t-mark">(公开成员函数)</span></td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E7.A4.BA.E4.BE.8B">示例</span></h3>
|
|
<div class="t-example">
|
|
<div class="t-example-live-link"></div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co2">#include <iostream></span>
|
|
<span class="co2">#include <mutex> // 对于 std::unique_lock</span>
|
|
<span class="co2">#include <shared_mutex></span>
|
|
<span class="co2">#include <thread></span>
|
|
|
|
<span class="kw1">class</span> ThreadSafeCounter <span class="br0">{</span>
|
|
<span class="kw1">public</span><span class="sy4">:</span>
|
|
ThreadSafeCounter<span class="br0">(</span><span class="br0">)</span> <span class="sy1">=</span> <span class="kw1">default</span><span class="sy4">;</span>
|
|
|
|
<span class="co1">// 多个线程/读者能同时读计数器的值。</span>
|
|
<span class="kw4">unsigned</span> <span class="kw4">int</span> get<span class="br0">(</span><span class="br0">)</span> <span class="kw4">const</span> <span class="br0">{</span>
|
|
<a href="cpp-thread-shared_lock.html"><span class="kw2167">std::<span class="me2">shared_lock</span></span></a><span class="sy1"><</span>std<span class="sy4">::</span><span class="me2">shared_mutex</span><span class="sy1">></span> lock<span class="br0">(</span>mutex_<span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="kw1">return</span> value_<span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="co1">// 只有一个线程/写者能增加/写线程的值。</span>
|
|
<span class="kw4">void</span> increment<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
|
|
<a href="cpp-thread-unique_lock.html"><span class="kw2166">std::<span class="me2">unique_lock</span></span></a><span class="sy1"><</span>std<span class="sy4">::</span><span class="me2">shared_mutex</span><span class="sy1">></span> lock<span class="br0">(</span>mutex_<span class="br0">)</span><span class="sy4">;</span>
|
|
value_<span class="sy2">++</span><span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="co1">// 只有一个线程/写者能重置/写线程的值。</span>
|
|
<span class="kw4">void</span> reset<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
|
|
<a href="cpp-thread-unique_lock.html"><span class="kw2166">std::<span class="me2">unique_lock</span></span></a><span class="sy1"><</span>std<span class="sy4">::</span><span class="me2">shared_mutex</span><span class="sy1">></span> lock<span class="br0">(</span>mutex_<span class="br0">)</span><span class="sy4">;</span>
|
|
value_ <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="kw1">private</span><span class="sy4">:</span>
|
|
mutable std<span class="sy4">::</span><span class="me2">shared_mutex</span> mutex_<span class="sy4">;</span>
|
|
<span class="kw4">unsigned</span> <span class="kw4">int</span> value_ <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
|
|
ThreadSafeCounter counter<span class="sy4">;</span>
|
|
|
|
<span class="kw4">auto</span> increment_and_print <span class="sy1">=</span> <span class="br0">[</span><span class="sy3">&</span>counter<span class="br0">]</span><span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
|
|
<span class="kw1">for</span> <span class="br0">(</span><span class="kw4">int</span> i <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span> i <span class="sy1"><</span> <span class="nu0">3</span><span class="sy4">;</span> i<span class="sy2">++</span><span class="br0">)</span> <span class="br0">{</span>
|
|
counter.<span class="me1">increment</span><span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <a href="cpp-thread-get_id.html"><span class="kw2148">std::<span class="me2">this_thread</span><span class="sy4">::</span><span class="me2">get_id</span></span></a><span class="br0">(</span><span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">' '</span> <span class="sy1"><<</span> counter.<span class="me1">get</span><span class="br0">(</span><span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
|
|
<span class="co1">// 注意:写入 std::cout 实际上也要由另一互斥同步。省略它以保持示例简洁。</span>
|
|
<span class="br0">}</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
|
|
<a href="cpp-thread-thread.html"><span class="kw2146">std::<span class="me2">thread</span></span></a> thread1<span class="br0">(</span>increment_and_print<span class="br0">)</span><span class="sy4">;</span>
|
|
<a href="cpp-thread-thread.html"><span class="kw2146">std::<span class="me2">thread</span></span></a> thread2<span class="br0">(</span>increment_and_print<span class="br0">)</span><span class="sy4">;</span>
|
|
|
|
thread1.<span class="me1">join</span><span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
|
thread2.<span class="me1">join</span><span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="co1">// 解释:下列输出在单核机器上生成。 thread1 开始时,它首次进入循环并调用 increment() ,</span>
|
|
<span class="co1">// 随后调用 get() 。然而,在它能打印返回值到 std::cout 前,调度器将 thread1 置于休眠</span>
|
|
<span class="co1">// 并唤醒 thread2 ,它显然有足够时间一次运行全部三个循环迭代。再回到 thread1 ,它仍在首个</span>
|
|
<span class="co1">// 循环迭代中,它最终打印其局部的计数器副本的值,即 1 到 std::cout ,再运行剩下二个循环。</span>
|
|
<span class="co1">// 多核机器上,没有线程被置于休眠,且输出更可能为递增顺序。</span></pre></div>
|
|
</div>
|
|
<p>可能的输出:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="text source-text">
|
|
<pre class="de1">123084176803584 2
|
|
123084176803584 3
|
|
123084176803584 4
|
|
123084185655040 1
|
|
123084185655040 5
|
|
123084185655040 6</pre></div>
|
|
</div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E5.8F.82.E9.98.85">参阅</span></h3>
|
|
<table class="t-dsc-begin">
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><a href="cpp-thread-shared_timed_mutex.html"><span class="t-lines"><span>shared_timed_mutex</span></span></a></div>
|
|
<div><span class="t-lines"><span><span class="t-mark-rev t-since-cxx14">(C++14)</span></span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>提供共享互斥设施并实现有时限锁定<br />
|
|
<span class="t-mark">(类)</span></td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="visualClear"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|