171 lines
20 KiB
HTML
171 lines
20 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::atomic_thread_fence</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_atomic_atomic_thread_fence 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>atomic_thread_fence</h1>
|
|
<div id="bodyContent">
|
|
<div id="contentSub"><span class="subpages">< <a href="cpp.html">cpp</a>‎ | <a href="cpp-atomic.html">atomic</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-atomic.html"><atomic></a></code></div>
|
|
</td>
|
|
<td></td>
|
|
<td></td>
|
|
</tr>
|
|
<tr class="t-dcl t-since-cxx11">
|
|
<td>
|
|
<div><span class="mw-geshi cpp source-cpp"><span class="kw4">extern</span> <span class="st0">"C"</span> <span class="kw4">void</span> atomic_thread_fence<span class="br0">(</span> <a href="cpp-atomic-memory_order.html"><span class="kw2092">std::<span class="me2">memory_order</span></span></a> order <span class="br0">)</span> <span class="kw1">noexcept</span><span class="sy4">;</span></span></div>
|
|
</td>
|
|
<td class="t-dcl-nopad"></td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></td>
|
|
</tr>
|
|
<tr class="t-dcl-sep">
|
|
<td></td>
|
|
<td></td>
|
|
<td></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<p>建立非原子和宽松原子访问的以 <code>order</code> 指示的<a href="cpp-atomic-memory_order.html">内存同步顺序</a>,而无关联的原子操作。</p>
|
|
<h4><span class="mw-headline" id=".E6.A0.85.E6.A0.8F.E5.8E.9F.E5.AD.90.E5.90.8C.E6.AD.A5">栅栏原子同步</span></h4>
|
|
<p>线程 A 中的释放栅栏 F 同步于线程 B 中的原子<a href="cpp-atomic-memory_order.html">获得操作</a> Y ,若</p>
|
|
<ul>
|
|
<li>存在原子存储 X (带任何内存顺序)</li>
|
|
<li>Y 读取 X 所写入的值(或会为 <a href="cpp-atomic-memory_order.html">X 所引领的释放序列</a>所写入的值,若 X 是释放操作)</li>
|
|
<li>F 在线程 A 中先序于 X</li>
|
|
</ul>
|
|
<p>此情况下,所有线程 A 中<a href="cpp-atomic-memory_order.html">先序于</a> F 的非原子和宽松原子存储将<a href="cpp-atomic-memory_order.html">先发生于</a>线程 B 中所有 Y 后的,来自同一位置的非原子和宽松原子加载。</p>
|
|
<h4><span class="mw-headline" id=".E5.8E.9F.E5.AD.90.E6.A0.85.E6.A0.8F.E5.90.8C.E6.AD.A5">原子栅栏同步</span></h4>
|
|
<p>线程 A 中的原子<a href="cpp-atomic-memory_order.html">释放操作</a> X 同步于线程 B 中的获得栅栏 F ,若</p>
|
|
<ul>
|
|
<li>存在原子读取 Y (带任何内存顺序)</li>
|
|
<li>Y 读取 X (或 <a href="cpp-atomic-memory_order.html">X 所引领的释放序列</a>)所写入的值</li>
|
|
<li>Y 在线程 B 中先序于 F</li>
|
|
</ul>
|
|
<p>此情况下,线程 A 中所有<a href="cpp-atomic-memory_order.html">先序于</a> X 的非原子和宽松原子存储,将<a href="cpp-atomic-memory_order.html">先发生于</a>线程 B 中所有 F 后的,来自同一位置的非原子和宽松原子加载。</p>
|
|
<h4><span class="mw-headline" id=".E6.A0.85.E6.A0.8F.E6.A0.85.E6.A0.8F.E5.90.8C.E6.AD.A5">栅栏栅栏同步</span></h4>
|
|
<p>线程 A 中的释放栅栏 FA 同步于线程 B 中的获得栅栏 FB ,若</p>
|
|
<ul>
|
|
<li>存在原子对象 M ,</li>
|
|
<li>线程 A 中存在修改 M 的原子写入 X (带任何内存顺序)</li>
|
|
<li>线程 A 中 FA 先序于 X</li>
|
|
<li>线程 B 中存在原子读取 Y (带任何内存顺序)</li>
|
|
<li>Y 读取 X 所写入的值(或会为 <a href="cpp-atomic-memory_order.html">X 所引领的释放序列</a>所写入的值,若 X 是释放操作)</li>
|
|
<li>线程 B 中 Y 先序于 FB</li>
|
|
</ul>
|
|
<p>此情况下,线程 A 中所有<a href="cpp-atomic-memory_order.html">先序于</a> FA 的非原子和宽松原子存储,将<a href="cpp-atomic-memory_order.html">先发生于</a>线程 B 中所有 FB 后的,来自同一位置的非原子和宽松原子加载。</p>
|
|
<h3><span class="mw-headline" id=".E5.8F.82.E6.95.B0">参数</span></h3>
|
|
<table class="t-par-begin">
|
|
<tr class="t-par">
|
|
<td>order</td>
|
|
<td>-</td>
|
|
<td>此栅栏所执行的内存顺序</td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E8.BF.94.E5.9B.9E.E5.80.BC">返回值</span></h3>
|
|
<p>(无)</p>
|
|
<h3><span class="mw-headline" id=".E6.B3.A8.E6.84.8F">注意</span></h3>
|
|
<p><code>atomic_thread_fence</code> 强加的同步制约强于带同一 <span class="t-lc"><a href="cpp-atomic-memory_order.html">std::memory_order</a></span> 的原子存储操作。在原子存储释放操作阻止所有前驱写入被移动到存储释放之后的同时,带 <code>memory_order_release</code> 顺序的 <code>atomic_thread_fence</code> 还阻止所有前驱写入被移动到后继存储之后。</p>
|
|
<p>栅栏栅栏同步能用于添加同步到数个宽松原子操作的序列,例如</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co1">// 全局</span>
|
|
<a href="cpp-string-basic_string.html"><span class="kw1230">std::<span class="me2">string</span></span></a> computation<span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="kw4">void</span> print<span class="br0">(</span> <a href="cpp-string-basic_string.html"><span class="kw1230">std::<span class="me2">string</span></span></a> <span class="br0">)</span><span class="sy4">;</span>
|
|
|
|
<a href="cpp-atomic-atomic.html"><span class="kw2066">std::<span class="me2">atomic</span></span></a><span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span> arr<span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span> <span class="sy1">=</span> <span class="br0">{</span> <span class="sy2">-</span><span class="nu0">1</span>, <span class="sy2">-</span><span class="nu0">1</span>, <span class="sy2">-</span><span class="nu0">1</span> <span class="br0">}</span><span class="sy4">;</span>
|
|
<a href="cpp-string-basic_string.html"><span class="kw1230">std::<span class="me2">string</span></span></a> data<span class="br0">[</span><span class="nu0">1000</span><span class="br0">]</span> <span class="co1">// 非原子数据</span>
|
|
|
|
<span class="co1">// 线程 A ,计算 3 个值</span>
|
|
<span class="kw4">void</span> ThreadA<span class="br0">(</span> <span class="kw4">int</span> v0, <span class="kw4">int</span> v1, <span class="kw4">int</span> v2 <span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<span class="co1">//assert( 0 <= v0, v1, v2 < 1000 );</span>
|
|
data<span class="br0">[</span>v0<span class="br0">]</span> <span class="sy1">=</span> computation<span class="br0">(</span>v0<span class="br0">)</span><span class="sy4">;</span>
|
|
data<span class="br0">[</span>v1<span class="br0">]</span> <span class="sy1">=</span> computation<span class="br0">(</span>v1<span class="br0">)</span><span class="sy4">;</span>
|
|
data<span class="br0">[</span>v2<span class="br0">]</span> <span class="sy1">=</span> computation<span class="br0">(</span>v2<span class="br0">)</span><span class="sy4">;</span>
|
|
std<span class="sy4">::</span><span class="me2">atomic_thread_fence</span><span class="br0">(</span><a href="cpp-atomic-memory_order.html"><span class="kw2096">std::<span class="me2">memory_order_release</span></span></a><span class="br0">)</span><span class="sy4">;</span>
|
|
<a href="cpp-atomic-atomic_store.html"><span class="kw2069">std::<span class="me2">atomic_store_explicit</span></span></a><span class="br0">(</span><span class="sy3">&</span>arr<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span>, v0, <a href="cpp-atomic-memory_order.html"><span class="kw2093">std::<span class="me2">memory_order_relaxed</span></span></a><span class="br0">)</span><span class="sy4">;</span>
|
|
<a href="cpp-atomic-atomic_store.html"><span class="kw2069">std::<span class="me2">atomic_store_explicit</span></span></a><span class="br0">(</span><span class="sy3">&</span>arr<span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span>, v1, <a href="cpp-atomic-memory_order.html"><span class="kw2093">std::<span class="me2">memory_order_relaxed</span></span></a><span class="br0">)</span><span class="sy4">;</span>
|
|
<a href="cpp-atomic-atomic_store.html"><span class="kw2069">std::<span class="me2">atomic_store_explicit</span></span></a><span class="br0">(</span><span class="sy3">&</span>arr<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span>, v2, <a href="cpp-atomic-memory_order.html"><span class="kw2093">std::<span class="me2">memory_order_relaxed</span></span></a><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="co1">// 线程 B ,打印已经计算的 0 与 3 之间的值。</span>
|
|
<span class="kw4">void</span> ThreadB<span class="br0">(</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<span class="kw4">int</span> v0 <span class="sy1">=</span> <a href="cpp-atomic-atomic_load.html"><span class="kw2071">std::<span class="me2">atomic_load_explicit</span></span></a><span class="br0">(</span><span class="sy3">&</span>arr<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span>, <a href="cpp-atomic-memory_order.html"><span class="kw2093">std::<span class="me2">memory_order_relaxed</span></span></a><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="kw4">int</span> v1 <span class="sy1">=</span> <a href="cpp-atomic-atomic_load.html"><span class="kw2071">std::<span class="me2">atomic_load_explicit</span></span></a><span class="br0">(</span><span class="sy3">&</span>arr<span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span>, <a href="cpp-atomic-memory_order.html"><span class="kw2093">std::<span class="me2">memory_order_relaxed</span></span></a><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="kw4">int</span> v2 <span class="sy1">=</span> <a href="cpp-atomic-atomic_load.html"><span class="kw2071">std::<span class="me2">atomic_load_explicit</span></span></a><span class="br0">(</span><span class="sy3">&</span>arr<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span>, <a href="cpp-atomic-memory_order.html"><span class="kw2093">std::<span class="me2">memory_order_relaxed</span></span></a><span class="br0">)</span><span class="sy4">;</span>
|
|
std<span class="sy4">::</span><span class="me2">atomic_thread_fence</span><span class="br0">(</span><a href="cpp-atomic-memory_order.html"><span class="kw2095">std::<span class="me2">memory_order_acquire</span></span></a><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="co1">// v0 、 v1 、 v2 可能全部或部分结果为 -1 。</span>
|
|
<span class="co1">// 其他情况下读取非原子数据是安全的,因为栅栏:</span>
|
|
<span class="kw1">if</span><span class="br0">(</span> v0 <span class="sy3">!</span><span class="sy1">=</span> <span class="sy2">-</span><span class="nu0">1</span> <span class="br0">)</span> <span class="br0">{</span> print<span class="br0">(</span> data<span class="br0">[</span>v0<span class="br0">]</span> <span class="br0">)</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
<span class="kw1">if</span><span class="br0">(</span> v1 <span class="sy3">!</span><span class="sy1">=</span> <span class="sy2">-</span><span class="nu0">1</span> <span class="br0">)</span> <span class="br0">{</span> print<span class="br0">(</span> data<span class="br0">[</span>v1<span class="br0">]</span> <span class="br0">)</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
<span class="kw1">if</span><span class="br0">(</span> v2 <span class="sy3">!</span><span class="sy1">=</span> <span class="sy2">-</span><span class="nu0">1</span> <span class="br0">)</span> <span class="br0">{</span> print<span class="br0">(</span> data<span class="br0">[</span>v2<span class="br0">]</span> <span class="br0">)</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E7.A4.BA.E4.BE.8B">示例</span></h3>
|
|
<div class="t-example">
|
|
<p>扫描邮箱数组,并只处理我们打算处理的一个,而无不必要的同步。 此示例使用原子栅栏同步。</p>
|
|
<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="kw4">const</span> <span class="kw4">int</span> num_mailboxes <span class="sy1">=</span> <span class="nu0">32</span><span class="sy4">;</span>
|
|
<a href="cpp-atomic-atomic.html"><span class="kw2066">std::<span class="me2">atomic</span></span></a><span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span> mailbox_receiver<span class="br0">[</span>num_mailboxes<span class="br0">]</span><span class="sy4">;</span>
|
|
<a href="cpp-string-basic_string.html"><span class="kw1230">std::<span class="me2">string</span></span></a> mailbox_data<span class="br0">[</span>num_mailboxes<span class="br0">]</span><span class="sy4">;</span>
|
|
|
|
<span class="co1">// 写者线程更新非原子共享数据</span>
|
|
<span class="co1">// 然后更新 mailbox_receiver[i] 如下</span>
|
|
mailbox_data<span class="br0">[</span>i<span class="br0">]</span> <span class="sy1">=</span> ...<span class="sy4">;</span>
|
|
<a href="cpp-atomic-atomic_store.html"><span class="kw2069">std::<span class="me2">atomic_store_explicit</span></span></a><span class="br0">(</span><span class="sy3">&</span>mailbox_receiver<span class="br0">[</span>i<span class="br0">]</span>, receiver_id, <a href="cpp-atomic-memory_order.html"><span class="kw2096">std::<span class="me2">memory_order_release</span></span></a><span class="br0">)</span><span class="sy4">;</span>
|
|
|
|
<span class="co1">// 读者线程需要检查所有 mailbox[i] ,但只需与一个同步</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> num_mailboxes<span class="sy4">;</span> <span class="sy2">++</span>i<span class="br0">)</span> <span class="br0">{</span>
|
|
<span class="kw1">if</span> <span class="br0">(</span><a href="cpp-atomic-atomic_load.html"><span class="kw2071">std::<span class="me2">atomic_load_explicit</span></span></a><span class="br0">(</span><span class="sy3">&</span>mailbox_receiver<span class="br0">[</span>i<span class="br0">]</span>, <a href="cpp-atomic-memory_order.html"><span class="kw2093">std::<span class="me2">memory_order_relaxed</span></span></a><span class="br0">)</span> <span class="sy1">==</span> my_id<span class="br0">)</span> <span class="br0">{</span>
|
|
std<span class="sy4">::</span><span class="me2">atomic_thread_fence</span><span class="br0">(</span><a href="cpp-atomic-memory_order.html"><span class="kw2095">std::<span class="me2">memory_order_acquire</span></span></a><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 恰与一个写者同步</span>
|
|
do_work<span class="br0">(</span> mailbox_data<span class="br0">[</span>i<span class="br0">]</span> <span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 保证观测到 atomic_store_explicit()</span>
|
|
<span class="co1">// 之前写者线程所做的任何事</span>
|
|
<span class="br0">}</span>
|
|
<span class="br0">}</span></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-atomic-memory_order.html"><span class="t-lines"><span>memory_order</span></span></a></div>
|
|
<div><span class="t-lines"><span><span class="t-mark-rev t-since-cxx11">(C++11)</span></span></span></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-atomic-atomic_signal_fence.html"><span class="t-lines"><span>atomic_signal_fence</span></span></a></div>
|
|
<div><span class="t-lines"><span><span class="t-mark-rev t-since-cxx11">(C++11)</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>
|