-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathc-11-memory-model.html
More file actions
129 lines (119 loc) · 40.6 KB
/
c-11-memory-model.html
File metadata and controls
129 lines (119 loc) · 40.6 KB
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>C++ | C++11 Memory Model</title>
<meta name="generator" content="VuePress 1.8.2">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
<meta name="description" content="Need for Memory Model, Fence example">
<meta property="og:site_name" content="DevTut">
<meta property="og:title" content="C++ | C++11 Memory Model">
<meta property="og:description" content="Need for Memory Model, Fence example">
<meta property="og:type" content="article">
<meta property="og:url" content="/cpp/c-11-memory-model.html">
<meta property="og:image" content="/logo.png">
<meta name="twitter:title" content="C++ | C++11 Memory Model">
<meta name="twitter:description" content="Need for Memory Model, Fence example">
<meta name="twitter:url" content="/cpp/c-11-memory-model.html">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="/logo.png">
<meta name="theme-color" content="#ffffff">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="msapplication-TileImage" content="/mstile-150x150.png">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="google-site-verification" content="76_rKXgwMVIjd-axJC_1zPV9OS4mEjvtgjYOWVkAdnQ">
<link rel="preload" href="/assets/css/0.styles.60619e34.css" as="style"><link rel="preload" href="/assets/js/app.1779e102.js" as="script"><link rel="preload" href="/assets/js/3.2cfa8016.js" as="script"><link rel="preload" href="/assets/js/623.11731ad1.js" as="script">
<link rel="stylesheet" href="/assets/css/0.styles.60619e34.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">DevTut</span></a> <div class="links"><form id="search-form" role="search" class="algolia-search-wrapper search-box"><input id="algolia-search-input" class="search-query"></form> <nav class="nav-links can-hide"> <a href="https://github.com/devtut/generate" target="_blank" rel="noopener noreferrer" class="repo-link">
GitHub
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"> <a href="https://github.com/devtut/generate" target="_blank" rel="noopener noreferrer" class="repo-link">
GitHub
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>C++</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/cpp/" aria-current="page" class="sidebar-link">Disclaimer</a></li><li><a href="/cpp/getting-started-with-cpp.html" class="sidebar-link">Getting started with C++</a></li><li><a href="/cpp/literals.html" class="sidebar-link">Literals</a></li><li><a href="/cpp/operator-precedence.html" class="sidebar-link">operator precedence</a></li><li><a href="/cpp/floating-point-arithmetic.html" class="sidebar-link">Floating Point Arithmetic</a></li><li><a href="/cpp/bit-operators.html" class="sidebar-link">Bit Operators</a></li><li><a href="/cpp/bit-manipulation.html" class="sidebar-link">Bit Manipulation</a></li><li><a href="/cpp/bit-fields.html" class="sidebar-link">Bit fields</a></li><li><a href="/cpp/arrays.html" class="sidebar-link">Arrays</a></li><li><a href="/cpp/iterators.html" class="sidebar-link">Iterators</a></li><li><a href="/cpp/basic-input-output-in-c.html" class="sidebar-link">Basic input/output in c++</a></li><li><a href="/cpp/loops.html" class="sidebar-link">Loops</a></li><li><a href="/cpp/file-i-o.html" class="sidebar-link">File I/O</a></li><li><a href="/cpp/cpp-streams.html" class="sidebar-link">C++ Streams</a></li><li><a href="/cpp/stream-manipulators.html" class="sidebar-link">Stream manipulators</a></li><li><a href="/cpp/flow-control.html" class="sidebar-link">Flow Control</a></li><li><a href="/cpp/metaprogramming.html" class="sidebar-link">Metaprogramming</a></li><li><a href="/cpp/const-keyword.html" class="sidebar-link">const keyword</a></li><li><a href="/cpp/mutable-keyword.html" class="sidebar-link">mutable keyword</a></li><li><a href="/cpp/friend-keyword.html" class="sidebar-link">Friend keyword</a></li><li><a href="/cpp/type-keywords.html" class="sidebar-link">Type Keywords</a></li><li><a href="/cpp/basic-type-keywords.html" class="sidebar-link">Basic Type Keywords</a></li><li><a href="/cpp/variable-declaration-keywords.html" class="sidebar-link">Variable Declaration Keywords</a></li><li><a href="/cpp/keywords.html" class="sidebar-link">Keywords</a></li><li><a href="/cpp/returning-several-values-from-a-function.html" class="sidebar-link">Returning several values from a function</a></li><li><a href="/cpp/polymorphism.html" class="sidebar-link">Polymorphism</a></li><li><a href="/cpp/references.html" class="sidebar-link">References</a></li><li><a href="/cpp/value-and-reference-semantics.html" class="sidebar-link">Value and Reference Semantics</a></li><li><a href="/cpp/c-function-call-by-value-vs-call-by-reference.html" class="sidebar-link">C++ function "call by value" vs. "call by reference"</a></li><li><a href="/cpp/copying-vs-assignment.html" class="sidebar-link">Copying vs Assignment</a></li><li><a href="/cpp/pointers.html" class="sidebar-link">Pointers</a></li><li><a href="/cpp/pointers-to-members.html" class="sidebar-link">Pointers to members</a></li><li><a href="/cpp/the-this-pointer.html" class="sidebar-link">The This Pointer</a></li><li><a href="/cpp/smart-pointers.html" class="sidebar-link">Smart Pointers</a></li><li><a href="/cpp/classes-structures.html" class="sidebar-link">Classes/Structures</a></li><li><a href="/cpp/function-overloading.html" class="sidebar-link">Function Overloading</a></li><li><a href="/cpp/operator-overloading.html" class="sidebar-link">Operator Overloading</a></li><li><a href="/cpp/function-template-overloading.html" class="sidebar-link">Function Template Overloading</a></li><li><a href="/cpp/virtual-member-functions.html" class="sidebar-link">Virtual Member Functions</a></li><li><a href="/cpp/inline-functions.html" class="sidebar-link">Inline functions</a></li><li><a href="/cpp/special-member-functions.html" class="sidebar-link">Special Member Functions</a></li><li><a href="/cpp/non-static-member-functions.html" class="sidebar-link">Non-Static Member Functions</a></li><li><a href="/cpp/constant-class-member-functions.html" class="sidebar-link">Constant class member functions</a></li><li><a href="/cpp/c-containers.html" class="sidebar-link">C++ Containers</a></li><li><a href="/cpp/namespaces.html" class="sidebar-link">Namespaces</a></li><li><a href="/cpp/header-files.html" class="sidebar-link">Header Files</a></li><li><a href="/cpp/using-declaration.html" class="sidebar-link">Using declaration</a></li><li><a href="/cpp/std-string.html" class="sidebar-link">std::string</a></li><li><a href="/cpp/std-array.html" class="sidebar-link">std::array</a></li><li><a href="/cpp/std-vector.html" class="sidebar-link">std::vector</a></li><li><a href="/cpp/std-map.html" class="sidebar-link">std::map</a></li><li><a href="/cpp/std-optional.html" class="sidebar-link">std::optional</a></li><li><a href="/cpp/std-function-to-wrap-any-element-that-is-callable.html" class="sidebar-link">std::function: To wrap any element that is callable</a></li><li><a href="/cpp/std-forward-list.html" class="sidebar-link">std::forward_list</a></li><li><a href="/cpp/std-pair.html" class="sidebar-link">std::pair</a></li><li><a href="/cpp/std-atomics.html" class="sidebar-link">std::atomics</a></li><li><a href="/cpp/std-variant.html" class="sidebar-link">std::variant</a></li><li><a href="/cpp/std-iomanip.html" class="sidebar-link">std::iomanip</a></li><li><a href="/cpp/std-any.html" class="sidebar-link">std::any</a></li><li><a href="/cpp/std-set-and-std-multiset.html" class="sidebar-link">std::set and std::multiset</a></li><li><a href="/cpp/std-integer-sequence.html" class="sidebar-link">std::integer_sequence</a></li><li><a href="/cpp/using-std-unordered-map.html" class="sidebar-link">Using std::unordered_map</a></li><li><a href="/cpp/standard-library-algorithms.html" class="sidebar-link">Standard Library Algorithms</a></li><li><a href="/cpp/the-iso-c-standard.html" class="sidebar-link">The ISO C++ Standard</a></li><li><a href="/cpp/inline-variables.html" class="sidebar-link">Inline variables</a></li><li><a href="/cpp/random-number-generation.html" class="sidebar-link">Random number generation</a></li><li><a href="/cpp/date-and-time-using-chrono-header.html" class="sidebar-link">Date and time using header</a></li><li><a href="/cpp/sorting.html" class="sidebar-link">Sorting</a></li><li><a href="/cpp/enumeration.html" class="sidebar-link">Enumeration</a></li><li><a href="/cpp/iteration.html" class="sidebar-link">Iteration</a></li><li><a href="/cpp/regular-expressions.html" class="sidebar-link">Regular expressions</a></li><li><a href="/cpp/implementation-defined-behavior.html" class="sidebar-link">Implementation-defined behavior</a></li><li><a href="/cpp/exceptions.html" class="sidebar-link">Exceptions</a></li><li><a href="/cpp/lambdas.html" class="sidebar-link">Lambdas</a></li><li><a href="/cpp/value-categories.html" class="sidebar-link">Value Categories</a></li><li><a href="/cpp/preprocessor.html" class="sidebar-link">Preprocessor</a></li><li><a href="/cpp/data-structures-in-c.html" class="sidebar-link">Data Structures in C++</a></li><li><a href="/cpp/templates.html" class="sidebar-link">Templates</a></li><li><a href="/cpp/expression-templates.html" class="sidebar-link">Expression templates</a></li><li><a href="/cpp/curiously-recurring-template-pattern-crtp.html" class="sidebar-link">Curiously Recurring Template Pattern (CRTP)</a></li><li><a href="/cpp/threading.html" class="sidebar-link">Threading</a></li><li><a href="/cpp/thread-synchronization-structures.html" class="sidebar-link">Thread synchronization structures</a></li><li><a href="/cpp/the-rule-of-three-five-and-zero.html" class="sidebar-link">The Rule of Three, Five, And Zero</a></li><li><a href="/cpp/raii-resource-acquisition-is-initialization.html" class="sidebar-link">RAII: Resource Acquisition Is Initialization</a></li><li><a href="/cpp/rtti-run-time-type-information.html" class="sidebar-link">RTTI: Run-Time Type Information</a></li><li><a href="/cpp/mutexes.html" class="sidebar-link">Mutexes</a></li><li><a href="/cpp/recursive-mutex.html" class="sidebar-link">Recursive Mutex</a></li><li><a href="/cpp/semaphore.html" class="sidebar-link">Semaphore</a></li><li><a href="/cpp/futures-and-promises.html" class="sidebar-link">Futures and Promises</a></li><li><a href="/cpp/atomic-types.html" class="sidebar-link">Atomic Types</a></li><li><a href="/cpp/type-erasure.html" class="sidebar-link">Type Erasure</a></li><li><a href="/cpp/explicit-type-conversions.html" class="sidebar-link">Explicit type conversions</a></li><li><a href="/cpp/unnamed-types.html" class="sidebar-link">Unnamed types</a></li><li><a href="/cpp/type-traits.html" class="sidebar-link">Type Traits</a></li><li><a href="/cpp/return-type-covariance.html" class="sidebar-link">Return Type Covariance</a></li><li><a href="/cpp/layout-of-object-types.html" class="sidebar-link">Layout of object types</a></li><li><a href="/cpp/type-inference.html" class="sidebar-link">Type Inference</a></li><li><a href="/cpp/typedef-and-type-aliases.html" class="sidebar-link">Typedef and type aliases</a></li><li><a href="/cpp/type-deduction.html" class="sidebar-link">type deduction</a></li><li><a href="/cpp/trailing-return-type.html" class="sidebar-link">Trailing return type</a></li><li><a href="/cpp/alignment.html" class="sidebar-link">Alignment</a></li><li><a href="/cpp/perfect-forwarding.html" class="sidebar-link">Perfect Forwarding</a></li><li><a href="/cpp/decltype.html" class="sidebar-link">decltype</a></li><li><a href="/cpp/sfinae-substitution-failure-is-not-an-error.html" class="sidebar-link">SFINAE (Substitution Failure Is Not An Error)</a></li><li><a href="/cpp/undefined-behavior.html" class="sidebar-link">Undefined Behavior</a></li><li><a href="/cpp/overload-resolution.html" class="sidebar-link">Overload resolution</a></li><li><a href="/cpp/move-semantics.html" class="sidebar-link">Move Semantics</a></li><li><a href="/cpp/pimpl-idiom.html" class="sidebar-link">Pimpl Idiom</a></li><li><a href="/cpp/auto.html" class="sidebar-link">auto</a></li><li><a href="/cpp/copy-elision.html" class="sidebar-link">Copy Elision</a></li><li><a href="/cpp/fold-expressions.html" class="sidebar-link">Fold Expressions</a></li><li><a href="/cpp/unions.html" class="sidebar-link">Unions</a></li><li><a href="/cpp/design-pattern-implementation-in-c.html" class="sidebar-link">Design pattern implementation in C++</a></li><li><a href="/cpp/singleton-design-pattern.html" class="sidebar-link">Singleton Design Pattern</a></li><li><a href="/cpp/user-defined-literals.html" class="sidebar-link">User-Defined Literals</a></li><li><a href="/cpp/memory-management.html" class="sidebar-link">Memory management</a></li><li><a href="/cpp/c-11-memory-model.html" aria-current="page" class="active sidebar-link">C++11 Memory Model</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/cpp/c-11-memory-model.html#need-for-memory-model" class="sidebar-link">Need for Memory Model</a></li><li class="sidebar-sub-header"><a href="/cpp/c-11-memory-model.html#fence-example" class="sidebar-link">Fence example</a></li></ul></li><li><a href="/cpp/scopes.html" class="sidebar-link">Scopes</a></li><li><a href="/cpp/static-assert.html" class="sidebar-link">static_assert</a></li><li><a href="/cpp/constexpr.html" class="sidebar-link">constexpr</a></li><li><a href="/cpp/one-definition-rule-odr.html" class="sidebar-link">One Definition Rule (ODR)</a></li><li><a href="/cpp/unspecified-behavior.html" class="sidebar-link">Unspecified behavior</a></li><li><a href="/cpp/argument-dependent-name-lookup.html" class="sidebar-link">Argument Dependent Name Lookup</a></li><li><a href="/cpp/attributes.html" class="sidebar-link">Attributes</a></li><li><a href="/cpp/recursion-in-c.html" class="sidebar-link">Recursion in C++</a></li><li><a href="/cpp/arithmitic-metaprogramming.html" class="sidebar-link">Arithmitic Metaprogramming</a></li><li><a href="/cpp/callable-objects.html" class="sidebar-link">Callable Objects</a></li><li><a href="/cpp/client-server-examples.html" class="sidebar-link">Client server examples</a></li><li><a href="/cpp/const-correctness.html" class="sidebar-link">Const Correctness</a></li><li><a href="/cpp/parameter-packs.html" class="sidebar-link">Parameter packs</a></li><li><a href="/cpp/build-systems.html" class="sidebar-link">Build Systems</a></li><li><a href="/cpp/concurrency-with-openmp.html" class="sidebar-link">Concurrency With OpenMP</a></li><li><a href="/cpp/resource-management.html" class="sidebar-link">Resource Management</a></li><li><a href="/cpp/storage-class-specifiers.html" class="sidebar-link">Storage class specifiers</a></li><li><a href="/cpp/linkage-specifications.html" class="sidebar-link">Linkage specifications</a></li><li><a href="/cpp/digit-separators.html" class="sidebar-link">Digit separators</a></li><li><a href="/cpp/c-incompatibilities.html" class="sidebar-link">C incompatibilities</a></li><li><a href="/cpp/side-by-side-comparisons-of-classic-c-examples-solved-via-c-vs-c-11-vs-c-14-vs-c-17.html" class="sidebar-link">Side by Side Comparisons of classic C++ examples solved via C++ vs C++11 vs C++14 vs C++17</a></li><li><a href="/cpp/compiling-and-building.html" class="sidebar-link">Compiling and Building</a></li><li><a href="/cpp/common-compile-linker-errors-gcc.html" class="sidebar-link">Common compile/linker errors (GCC)</a></li><li><a href="/cpp/more-undefined-behaviors-in-c.html" class="sidebar-link">More undefined behaviors in C++</a></li><li><a href="/cpp/unit-testing-in-c.html" class="sidebar-link">Unit Testing in C++</a></li><li><a href="/cpp/c-debugging-and-debug-prevention-tools-techniques.html" class="sidebar-link">C++ Debugging and Debug-prevention Tools & Techniques</a></li><li><a href="/cpp/optimization-in-c.html" class="sidebar-link">Optimization in C++</a></li><li><a href="/cpp/optimization.html" class="sidebar-link">Optimization</a></li><li><a href="/cpp/profiling.html" class="sidebar-link">Profiling</a></li><li><a href="/cpp/refactoring-techniques.html" class="sidebar-link">Refactoring Techniques</a></li><li><a href="/cpp/internationalization-in-c.html" class="sidebar-link">Internationalization in C++</a></li><li><a href="/cpp/contributors.html" class="sidebar-link">The Contributors</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="c-11-memory-model"><a href="#c-11-memory-model" class="header-anchor">#</a> C++11 Memory Model</h1> <h2 id="need-for-memory-model"><a href="#need-for-memory-model" class="header-anchor">#</a> Need for Memory Model</h2> <div class="language-cpp extra-class"><pre class="language-cpp"><code><span class="token keyword">int</span> x<span class="token punctuation">,</span> y<span class="token punctuation">;</span>
<span class="token keyword">bool</span> ready <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
x <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
y <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span>
ready <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">void</span> <span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>ready<span class="token punctuation">)</span>
std<span class="token double-colon punctuation">::</span>cout <span class="token operator"><<</span> x <span class="token operator">+</span> y<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>One thread calls the <code>init()</code> function while another thread (or signal handler) calls the <code>use()</code> function. One might expect that the <code>use()</code> function will either print <code>5</code> or do nothing. This may not always be the case for several reasons:</p> <li>
The CPU may reorder the writes that happen in `init()` so that the code that actually executes might look like:
<div class="language-cpp extra-class"><pre class="language-cpp"><code><span class="token keyword">void</span> <span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
ready <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
x <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
y <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div></li> <li>
The CPU may reorder the reads that happen in `use()` so that the actually executed code might become:
<div class="language-cpp extra-class"><pre class="language-cpp"><code><span class="token keyword">void</span> <span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">int</span> local_x <span class="token operator">=</span> x<span class="token punctuation">;</span>
<span class="token keyword">int</span> local_y <span class="token operator">=</span> y<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>ready<span class="token punctuation">)</span>
std<span class="token double-colon punctuation">::</span>cout <span class="token operator"><<</span> local_x <span class="token operator">+</span> local_y<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div></li> <li>
An optimizing C++ compiler may decide to reorder the program in similar way.
</li> <p>Such reordering cannot change the behavior of a program running in single thread because a thread cannot interleave the calls to <code>init()</code> and <code>use()</code>. On the other hand in a multi-threaded setting one thread may see part of the writes performed by the other thread where it may happen that <code>use()</code> may see <code>ready==true</code> and garbage in <code>x</code> or <code>y</code> or both.</p> <p>The C++ Memory Model allows the programmer to specify which reordering operations are permitted and which are not, so that a multi-threaded program would also be able to behave as expected. The example above can be rewritten in thread-safe way like this:</p> <div class="language-cpp extra-class"><pre class="language-cpp"><code><span class="token keyword">int</span> x<span class="token punctuation">,</span> y<span class="token punctuation">;</span>
std<span class="token double-colon punctuation">::</span>atomic<span class="token operator"><</span><span class="token keyword">bool</span><span class="token operator">></span> ready<span class="token punctuation">{</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
x <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
y <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span>
ready<span class="token punctuation">.</span><span class="token function">store</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> std<span class="token double-colon punctuation">::</span>memory_order_release<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">void</span> <span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>ready<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span>std<span class="token double-colon punctuation">::</span>memory_order_acquire<span class="token punctuation">)</span><span class="token punctuation">)</span>
std<span class="token double-colon punctuation">::</span>cout <span class="token operator"><<</span> x <span class="token operator">+</span> y<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>Here <code>init()</code> performs <strong>atomic store-release</strong> operation. This not only stores the value <code>true</code> into <code>ready</code>, but also tells the compiler that it cannot move this operation before write operations that are <strong>sequenced before</strong> it.</p> <p>The <code>use()</code> function does an <strong>atomic load-acquire</strong> operation. It reads the current value of <code>ready</code> and also forbids the compiler from placing read operations that are <strong>sequenced after</strong> it to <strong>happen before</strong> the <strong>atomic load-acquire</strong>.</p> <p>These atomic operations also cause the compiler to put whatever hardware instructions are needed to inform the CPU to refrain from the unwanted reorderings.</p> <p>Because the <strong>atomic store-release</strong> is to the same memory location as the <strong>atomic load-acquire</strong>, the memory model stipulates that if the <strong>load-acquire</strong> operation sees the value written by the <strong>store-release</strong> operation, then all writes performed by <code>init()</code>'s thread prior to that <strong>store-release</strong> will be visible to loads that <code>use()</code>'s thread executes after its <strong>load-acquire</strong>. That is if <code>use()</code> sees <code>ready==true</code>, then it is guaranteed to see <code>x==2</code> and <code>y==3</code>.</p> <p>Note that the compiler and the CPU are still allowed to write to <code>y</code> before writing to <code>x</code>, and similarly the reads from these variables in <code>use()</code> can happen in any order.</p> <h2 id="fence-example"><a href="#fence-example" class="header-anchor">#</a> Fence example</h2> <p>The example above can also be implemented with fences and relaxed atomic operations:</p> <div class="language-cpp extra-class"><pre class="language-cpp"><code><span class="token keyword">int</span> x<span class="token punctuation">,</span> y<span class="token punctuation">;</span>
std<span class="token double-colon punctuation">::</span>atomic<span class="token operator"><</span><span class="token keyword">bool</span><span class="token operator">></span> ready<span class="token punctuation">{</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
x <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
y <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span>
<span class="token function">atomic_thread_fence</span><span class="token punctuation">(</span>std<span class="token double-colon punctuation">::</span>memory_order_release<span class="token punctuation">)</span><span class="token punctuation">;</span>
ready<span class="token punctuation">.</span><span class="token function">store</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> std<span class="token double-colon punctuation">::</span>memory_order_relaxed<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">void</span> <span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>ready<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span>std<span class="token double-colon punctuation">::</span>memory_order_relaxed<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token function">atomic_thread_fence</span><span class="token punctuation">(</span>std<span class="token double-colon punctuation">::</span>memory_order_acquire<span class="token punctuation">)</span><span class="token punctuation">;</span>
std<span class="token double-colon punctuation">::</span>cout <span class="token operator"><<</span> x <span class="token operator">+</span> y<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>If the atomic load operation sees the value written by the atomic store then the store happens before the load, and so do the fences: the release fence happens before the acquire fence making the writes to <code>x</code> and <code>y</code> that precede the release fence to become visible to the <code>std::cout</code> statement that follows the acquire fence.</p> <p>A fence might be beneficial if it can reduce the overall number of acquire, release or other synchronization operations. For example:</p> <div class="language-cpp extra-class"><pre class="language-cpp"><code><span class="token keyword">void</span> <span class="token function">block_and_use</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token operator">!</span>ready<span class="token punctuation">.</span><span class="token function">load</span><span class="token punctuation">(</span>std<span class="token double-colon punctuation">::</span>memory_order_relaxed<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">;</span>
<span class="token function">atomic_thread_fence</span><span class="token punctuation">(</span>std<span class="token double-colon punctuation">::</span>memory_order_acquire<span class="token punctuation">)</span><span class="token punctuation">;</span>
std<span class="token double-colon punctuation">::</span>cout <span class="token operator"><<</span> x <span class="token operator">+</span> y<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>The <code>block_and_use()</code> function spins until the <code>ready</code> flag is set with the help of relaxed atomic load. Then a single acquire fence is used to provide the needed memory ordering.</p> <h4 id="remarks"><a href="#remarks" class="header-anchor">#</a> Remarks</h4> <p>Different threads trying to access the same memory location participate in a <strong>data race</strong> if at least one of the operations is a modification (also known as <strong>store operation</strong>). These <strong>data races</strong> cause <strong>undefined behavior</strong>. To avoid them one needs to prevent these threads from concurrently executing such conflicting operations.</p> <p>Synchronization primitives (mutex, critical section and the like) can guard such accesses. The Memory Model introduced in C++11 defines two new portable ways to synchronize access to memory in multi-threaded environment: atomic operations and fences.</p> <h3 id="atomic-operations"><a href="#atomic-operations" class="header-anchor">#</a> Atomic Operations</h3> <p>It is now possible to read and write to given memory location by the use of <strong>atomic load</strong> and <strong>atomic store</strong> operations. For convenience these are wrapped in the <code>std::atomic<t></code> template class. This class wraps a value of type <code>t</code> but this time <strong>loads</strong> and <strong>stores</strong> to the object are atomic.</p> <p>The template is not available for all types. Which types are available is implementation specific, but this usually includes most (or all) available integral types as well as pointer types. So that <code>std::atomic<unsigned></code> and <code>std::atomic<std::vector<foo> *></code> should be available, while <code>std::atomic<std::pair<bool,char>></code> most probably wont be.</p> <p>Atomic operations have the following properties:</p> <ul><li>All atomic operations can be performed concurrently from multiple threads without causing undefined behavior.</li> <li>An <strong>atomic load</strong> will see either the initial value which the atomic object was constructed with, or the value written to it via some <strong>atomic store</strong> operation.</li> <li><strong>Atomic stores</strong> to the same atomic object are ordered the same in all threads. If a thread has already seen the value of some <strong>atomic store</strong> operation, subsequent <strong>atomic load</strong> operations will see either the same value, or the value stored by subsequent <strong>atomic store</strong> operation.</li> <li><strong>Atomic read-modify-write</strong> operations allow <strong>atomic load</strong> and <strong>atomic store</strong> to happen without other <strong>atomic store</strong> in between. For example one can atomically increment a counter from multiple threads, and no increment will be lost regardless of the contention between the threads.</li> <li>Atomic operations receive an optional <code>std::memory_order</code> parameter which defines what additional properties the operation has regarding other memory locations.</li></ul> <table><thead><tr><th>std::memory_order</th> <th>Meaning</th></tr></thead> <tbody><tr><td><code>std::memory_order_relaxed</code></td> <td>no additional restrictions</td></tr> <tr><td><code>std::memory_order_release</code> → <code>std::memory_order_acquire</code></td> <td>if <code>load-acquire</code> sees the value stored by <code>store-release</code> then stores <strong>sequenced before</strong> the <code>store-release</code> happen before loads sequenced after the <strong>load acquire</strong></td></tr> <tr><td><code>std::memory_order_consume</code></td> <td>like <code>memory_order_acquire</code> but only for dependent loads</td></tr> <tr><td><code>std::memory_order_acq_rel</code></td> <td>combines <code>load-acquire</code> and <code>store-release</code></td></tr> <tr><td><code>std::memory_order_seq_cst</code></td> <td>sequential consistency</td></tr></tbody></table> <p>These memory order tags allow three different memory ordering disciplines: <strong>sequential consistency</strong>, <strong>relaxed</strong>, and <strong>release-acquire</strong> with its sibling <strong>release-consume</strong>.</p> <h3 id="sequential-consistency"><a href="#sequential-consistency" class="header-anchor">#</a> Sequential Consistency</h3> <p>If no memory order is specified for an atomic operation, the order defaults to <strong>sequential consistency</strong>. This mode can also be explicitly selected by tagging the operation with <code>std::memory_order_seq_cst</code>.</p> <p>With this order no memory operation can cross the atomic operation. All memory operations sequenced before the atomic operation happen before the atomic operation and the atomic operation happens before all memory operations that are sequenced after it. This mode is probably the easiest one to reason about but it also leads to the greatest penalty to performance. It also prevents all compiler optimizations that might otherwise try to reorder operations past the atomic operation.</p> <h3 id="relaxed-ordering"><a href="#relaxed-ordering" class="header-anchor">#</a> Relaxed Ordering</h3> <p>The opposite to <strong>sequential consistency</strong> is the <strong>relaxed</strong> memory ordering. It is selected with the <code>std::memory_order_relaxed</code> tag. Relaxed atomic operation will impose no restrictions on other memory operations. The only effect that remains, is that the operation is itself still atomic.</p> <h3 id="release-acquire-ordering"><a href="#release-acquire-ordering" class="header-anchor">#</a> Release-Acquire Ordering</h3> <p>An <strong>atomic store</strong> operation can be tagged with <code>std::memory_order_release</code> and an <strong>atomic load</strong> operation can be tagged with <code>std::memory_order_acquire</code>. The first operation is called <strong>(atomic) store-release</strong> while the second is called <strong>(atomic) load-acquire</strong>.</p> <p>When <strong>load-acquire</strong> sees the value written by a <strong>store-release</strong> the following happens: all store operations sequenced before the <strong>store-release</strong> become visible to (<strong>happen before</strong>) load operations that are sequenced after the <strong>load-acquire</strong>.</p> <p>Atomic read-modify-write operations can also receive the cumulative tag <code>std::memory_order_acq_rel</code>. This makes the <strong>atomic load</strong> portion of the operation an <strong>atomic load-acquire</strong> while the <strong>atomic store</strong> portion becomes <strong>atomic store-release</strong>.</p> <p>The compiler is not allowed to move store operations after an <strong>atomic store-release</strong> operation. It is also not allowed to move load operations before <strong>atomic load-acquire</strong> (or <strong>load-consume</strong>).</p> <p>Also note that there is no <strong>atomic load-release</strong> or <strong>atomic store-acquire</strong>. Attempting to create such operations makes them <strong>relaxed</strong> operations.</p> <h3 id="release-consume-ordering"><a href="#release-consume-ordering" class="header-anchor">#</a> Release-Consume Ordering</h3> <p>This combination is similar to <strong>release-acquire</strong>, but this time the <strong>atomic load</strong> is tagged with <code>std::memory_order_consume</code> and becomes <strong>(atomic) load-consume</strong> operation. This mode is the same as <strong>release-acquire</strong> with the only difference that among the load operations sequenced after the <strong>load-consume</strong> only these depending on the value loaded by the <strong>load-consume</strong> are ordered.</p> <h3 id="fences"><a href="#fences" class="header-anchor">#</a> Fences</h3> <p>Fences also allow memory operations to be ordered between threads. A fence is either a release fence or acquire fence.</p> <p>If a release fence happens before an acquire fence, then stores sequenced before the release fence are visible to loads sequenced after the acquire fence. To guarantee that the release fence happens before the acquire fence one may use other synchronization primitives including relaxed atomic operations.</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/devtut/generate/edit/master/docs/cpp/c-11-memory-model.md" target="_blank" rel="noopener noreferrer">Edit this page on GitHub</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
←
<a href="/cpp/memory-management.html" class="prev">
Memory management
</a></span> <span class="next"><a href="/cpp/scopes.html">
Scopes
</a>
→
</span></p></div> </main></div><div class="global-ui"><!----></div></div>
<script src="/assets/js/app.1779e102.js" defer></script><script src="/assets/js/3.2cfa8016.js" defer></script><script src="/assets/js/623.11731ad1.js" defer></script>
</body>
</html>