I have introduced In the post Sequential Consistency the default memory model. This model, in which all operations in all threads takes place in a global time clock, has a big advantage but also a big disadvantage.
Heavyweight synchronization
The big advantage of sequential consistency is, that it matches our intuition of many threads running in parallel. The big disadvantages are, that the system has a lot of work to do to synchronise all the threads.
The following program synchronises the producer and the consumer thread with the help of sequential consistency.
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
|
// producerConsumer.cpp
#include <atomic>
#include <iostream>
#include <string>
#include <thread>
std::string work;
std::atomic<bool> ready(false);
void consumer(){
while(!ready.load()){}
std::cout<< work << std::endl;
}
void producer(){
work= "done";
ready=true;
}
int main(){
std::thread prod(producer);
std::thread con(consumer);
prod.join();
con.join();
}
|
The output of the program is concise and interesting.

Because of the sequential consistency, the program execution is totally deterministic. It always displays "done".
The graphic hit the spot. The consumer thread waits in the while-loop until the atomic variable ready is set to true. In case that happens, the consumer threads continue with their work.

It easy to reason, that the program will always return "done". I have only to use the two characteristics of sequential consistency. On one hand, both threads execute their instructions in the source code order, on the other hand, each thread sees the operations of the other thread in the same order. So both threads are following the same global time clock. This time clock will also hold - with the help of the while(!ready.load()){}-loop - for the synchronisation of the producer and the consumer thread.
But I can do the reasoning a lot more formal by using the terminology of the memory model. So the formal version:
=> Means it follows in the next lines:
- work= "done" is sequenced-before ready=true => work= "done" happens-before ready=true
- while(!ready.load()){} is sequenced-before std::cout<< work << std::endl => while(!ready.load()){} happens-before std::cout<< work << std::endl
- ready= true synchronizes-with while(!ready.load()){} => ready= true inter-thread happens-before while (!ready.load()){} => ready= true happens-before while (!ready.load()){}
=> Because the happens-before relation is transitive, it follows t: work= "done" happens-before ready= true happens-before while(!ready.load()){} happens-before std::cout<< work << std::endl
From the sequential consistency to the acquire-release semantic
A thread sees the operations of another thread and therefore of all other threads in the same order. The key characteristic of the sequential consistency will not hold, if we use the acquire-release semantic for atomic operations. This is an area, in which C# or Java will not follow. But that's also an area, in which our intuition begins to wane.
There is no global synchronization between threads in the acquire-release semantic, there is only a synchronisation between atomic operations on the same atomic variable. So a write operation on one thread synchronises with a read operation on another thread on the same atomic variable. This synchronization relation on the same atomic variable helps to establish a happens-before relation between atomic variables and therefore between threads.
What's next?
The details of the acquire-release semantic will follow in the next post. This includes an optimized spinlock.
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 Dominik Vošček.
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 
My special thanks to PVS-Studio 
My special thanks to Tipi.build 
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
- Phone: +49 7472 917441
- Mobil:: +49 176 5506 5086
- Mail: This email address is being protected from spambots. You need JavaScript enabled to view it.
- German Seminar Page: www.ModernesCpp.de
- Mentoring Page: www.ModernesCpp.org
Modernes C++,

Comments
even a weblog from start to end.
So good to find someone with a bit of genuine thoughts on this issue.
Seriously.. many thanks for starting this up.
This site can be something that's needed on the net, someone with some originality!
Also visit my web site ... UnaRStupke: http://www.dashengxu.com/comment/html/index.php?page=1&id=60119
RSS feed for comments to this post