Sequential Consistency

Contents[Show]

The atomics are the base of the C++ memory model. Per default, sequential consistency is applied.

The strong C++ memory model

In 2004 Java 5.0 gets its current memory model, and in 2011 C++.  Before that, Java had an erroneous memory model, and C++ had no memory model. Who thinks that this is the endpoint of a long process is wrong. The foundations of multithreading programming are 40 to 50 years old. So Leslie Lamport defined 1979 the concept of sequential consistency.

Sequential consistency provides two guarantees.

  1. The instructions of a program are executed in source code order.
  2. There is a global order of all operations on all threads.

Before I look deeper into these two guarantees, I explicitly emphasize them. The statements only hold for atomics but influence non-atomics.

The simple graphic displays two threads. Each thread is storing its variable x or y, loads the other variables y and x, and stores them in the variable res1 or res2.

 

twoAtomics

 

The operations take place on atomics, and so they are atomic. By default, sequential consistency applies. But the question is. In which order can the statements take place?

The first guarantee of sequential consistency is that the instruction will be executed in the order of the source code. That is easy. No store operation can overtake a load operation.

The second guarantee of sequential consistency is that all threads' instructions must follow a global order. That means, in that concrete case, that thread 2 sees the operations of thread 1 in the same order in which thread 1 executes them. This is the key observation. Thread 2 sees all operations of thread 1 in the source code order of thread 1. The same holds from the perspective of thread 1. So you can think about characteristic 2 as a global counter, which all threads must obey. The global counter is the global order.

We're not done with our riddle right now. What is still missing is to look at the different interleaving executions of the two threads. So the following six interleavings of the two threads are possible.

atomicInterleavingEng

That was easy. Or?

 

Rainer D 6 P2 540x540Modernes C++ Mentoring

Be part of my mentoring programs:

 

 

 

 

Do you want to stay informed about my mentoring programs: Subscribe via E-Mail.

From the strong to the weak memory model

I want to refer to the picture of the contract between the programmer and the system.

The programmer uses atomics in this particular example. So he obeys his part of the contract by using them correctly. The system guarantees him a well-defined program behavior without data races. In addition to that, the system can execute the four operations in each combination. If the programmer uses the relaxed semantic, the pillars of the contract dramatically change. On the one hand, it is much more difficult for the programmer to apply the contract correctly. On the other hand, the system has a lot more optimization possibilities. With the relaxed semantic - also called weak memory model - many more combinations of the four operations are possible. The counter-intuitive behavior is that thread 1 can see the operations of thread 2 in a different order. So there is no picture of a global counter. From the perspective of thread 1 it is possible that the operation res= y.load() overtakes x.store().

There are a few more models between the sequential consistency and the relaxed-semantic. The most important one is the acquire-release semantic. I think you already guess it. With acquire-release semantics, the programmer must obey weaker rules than sequential consistency. But the system has more optimization possibilities. The acquire-release semantic is the key to a deeper understanding of multithreading programming because the threads will be synchronized at specific synchronization points in the code. Without these synchronization points, there is no well-defined behavior of threads, tasks or condition variables possible. More about that in the following post.  

What's next?

The next post will provide a deeper look into atomics. But we stick with the strong C++ memory model. (Proofreader Alexey Elymanov)

 

 

 

 

Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Matthieu Bolt, Stephen Kelley, Kyle Dean, Tusar Palauri, Dmitry Farberov, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, Ann Shatoff, and Rob North.

 

Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, and Slavko Radman.

 

 

My special thanks to Embarcadero CBUIDER STUDIO FINAL ICONS 1024 Small

 

My special thanks to PVS-Studio PVC Logo

 

My special thanks to Tipi.build tipi.build logo

 

My special thanks to Take Up code TakeUpCode 450 60

 

Seminars

I'm happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.

Bookable (Online)

German

Standard Seminars (English/German)

Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.

  • C++ - The Core Language
  • C++ - The Standard Library
  • C++ - Compact
  • C++11 and C++14
  • Concurrency with Modern C++
  • Design Pattern and Architectural Pattern with C++
  • Embedded Programming with Modern C++
  • Generic Programming (Templates) with C++

New

  • Clean Code with Modern C++
  • C++20

Contact Me

Modernes C++,

RainerGrimmDunkelBlauSmall

Comments   

0 #71 Eric 2017-07-29 18:15
I spent a lot of time to locate something such as this
Quote
0 #72 Victoria 2017-07-29 18:41
It works quite well for me
Quote
0 #73 Abdul 2017-07-29 22:07
It works really well for me
Quote
0 #74 Grover 2017-07-29 22:31
Thank you for the excellent post
Quote
0 #75 Julia 2017-07-29 22:39
I enjoy the report
Quote
0 #76 Selene 2017-07-30 00:40
I like the article
Quote
-1 #77 Elouise 2017-07-30 07:41
It works very well for me
Quote
0 #78 Magda 2017-07-30 13:25
Thanks, it is very informative
Quote
0 #79 Roxie 2017-08-02 11:43
This is truly useful, thanks.
Quote
+2 #80 mat 2018-04-29 17:58
The first guarantee of the sequential consistency is that the instruction will be executed in the order of the source code. That is easy. "No store operation can overtake a load operation." Why? is that between store and load operations within the same atomic variable or with two different atomic variables that store operation could not overtake a load operation?
Quote

Stay Informed about my Mentoring

 

Mentoring

English Books

Course: Modern C++ Concurrency in Practice

Course: C++ Standard Library including C++14 & C++17

Course: Embedded Programming with Modern C++

Course: Generic Programming (Templates)

Course: C++ Fundamentals for Professionals

Course: The All-in-One Guide to C++20

Course: Master Software Design Patterns and Architecture in C++

Subscribe to the newsletter (+ pdf bundle)

All tags

Blog archive

Source Code

Visitors

Today 3667

Yesterday 4371

Week 39474

Month 169599

All 12057365

Currently are 180 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments