With the new C++11 Standard, C++ faces the first-time challenges of multicore architectures. The 2011 published standard defines how a C++ program has to behave in the presence of multiple threads. The C++11 multithreading capabilities are composed of two components. On the one hand, this is the defined memory model, and on the other hand, the standardized threading interface.
A well-defined memory model
The defined memory model is the necessary basis so that multithreaded programming makes sense in C++. Thus, the memory model has to give answers to the following questions.
- What are atomic operations?
- Which order of operations is ensured?
- When are the memory effects of operations visible?
To 1: Atomic operations are operations that follow the first three letters of the famous ACID Idioms from the database theory. Atomic operations are atomic (A), going from one consistent (C) state to the next, and are executed in isolation (I). In particular, this means that no other thread can observe an intermediate state of an atomic operation. The incrementation atomVar++ shows the consistency and isolation of an atomic operation very nicely. If atomVar is an atomic variable, atomVar can have only the old or the new value. The consistency of the variable atomVar is that it only changes from one state to the other, and the isolation is that another thread cannot observe any intermediate value.
To 2: The compiler, which translates the program into assembler instructions, and the processor that executes the assembler instructions, can rearrange the operations. Mostly this is done for performance reasons. In addition, the various tiers of storage (cache) offer the possibility of providing the result of the operations in a delayed way.
To 3: Since one thread may see an operation on a variable later than another, the threads must obey specific rules.
The standardized threading interface
The standardized threading interface in C++11 is composed of the following components.
- Thread local data
- Condition variables
To 1: Threads are the basic building blocks of multithreaded programming. They do their work autonomously, are parameterized by arguments, and interact with other threads via shared variables.
To 2:Tasks is a relatively modern concept. Tasks consist of two components, which are connected by a communication channel. As an endpoint of the channel, one component produces the result while the other endpoint consumes it. The producer is called Promise, the consumer Future.
To 3: Thread local data is data – such as it is easy to guess from the name- that explicitly belongs to one thread.
To 4:Condition variables enables it to implement producer/consumer workflows. The consumer waits for the notification of the producer so that he can continue his work.
What will come with C++17 and C++20?
The next C++ standards are planned for 2017 and 2020. C++17 and C++20 will consist of many extensions around the multithreading capabilities of the existing standard. Because the existing functionality is very basic. These changes will likely include the following three exciting features:
- Latches and barriers
- Transactional memory
- Automatically parallelizing or vectorizing algorithms of the Standard Template Library (STL)
To 1: Latches and barriers are similar to semaphores.
To 2:Transactional memory is, in simple words, the idea of ACID applied (again, only the first three letters) to code. That means the code is annotated as transactional memory and optimistically executed without synchronization with other threads. At the end of the transaction, the results will only be published if the initial conditions are still valid. If not, the outcome of the result is rejected, and the transaction is again executed. While mutexes always lock the critical area, the transaction is not locked, but the result may be discarded. A critical area is a section of code that, at most, one thread can enter at a time.
To 3: While parallelizing algorithms distribute the operations on their containers on multiple threads, vectorizing algorithms perform their operations on several container elements in a single step.
In the following few articles, I will look deeper into the components of the C++ memory model and the standardized threading interface. My focus is not to elaborate on every detail. The details are very well documented in the current C++ standard 14882:2014 or in the webpage cppreference.com.
My focus will particularly be on the following few articles to show you typical errors in dealing with multithreaded programs and suggest solutions. For this purpose, I will incorporate as much theory to understand the problem and the solution as necessary. I start with the standardized threading interface.
In the next post, I will deal with the creation of threads.
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, 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, Rob North, Bhavith C Achar, and Marco Parri Empoli.
Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, Slavko Radman, and David Poole.
|My special thanks to Embarcadero|
|My special thanks to PVS-Studio|
|My special thanks to Tipi.build|
|My special thanks to Take Up Code|
I’m happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.
- Embedded Programmierung mit modernem C++ 12.12.2023 – 14.12.2023 (Präsenzschulung, Termingarantie)
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++
- Clean Code with Modern C++
- Phone: +49 7472 917441
- Mobil:: +49 176 5506 5086
- Mail: schulung@ModernesCpp.de
- German Seminar Page: www.ModernesCpp.de
- Mentoring Page: www.ModernesCpp.org
Modernes C++ Mentoring,