Multithreading in Modern C++

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. This is, on the one hand, the defined memory model, which is 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.

  1. What are atomic operations?
  2. Which order of operations is ensured?
  3. 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). This means in particular, 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 nice. 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 changes only from one state to the other and the isolation, that another thread can not observe any intermediate value.

To 2: Both the compiler that translates the program into assembler instructions and the processor that executes the assembler instructions, can rearrange the operations. Most often this is for performance reasons. In addition the various tiers of storage (cache) posse the possibility to provide the result of the operations in a delayed way.

To 3: Since it is quite possible that one thread sees an operation on a variable later than another, the threads have to obey certain rules.

The standardized threading interface

The standardized threading interface in C++11 is composed of the following components.

 

Rainer D 6 P2 500x500Modernes C++ Mentoring

Be part of my mentoring programs:

  • "Fundamentals for C++ Professionals" (open)
  • "Design Patterns and Architectural Patterns with C++" (open)
  • "C++20: Get the Details" (open)
  • "Concurrency with Modern C++" (starts March 2024)
  • Do you want to stay informed: Subscribe.

     

    1. Threads
    2. Tasks
    3. Thread local data
    4. 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 are a relatively modern concept. Tasks consist of two components, which are connected by a communication channel. One component as endpoint of the channel 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 interesting features:

    1. Latches and barriers
    2. Transactional memory
    3. 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 the code is 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 the critical area is always locked by mutexes, the transaction is not locked, but possibly the result will be discarded. A critical area is a section of code, that at most one thread is allowed to 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 elements of their container in a single step.

    My Plan

    In the next 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 in the next few articles to show you typical errors in dealing with multithreaded programs and of course, 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.

    What’s next?

    In the next post, I 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, 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, Marco Parri Empoli, moon, Philipp Lenk, Hobsbawm, and Charles-Jianye Chen.

    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
    My special thanks to SHAVEDYAKS

    Seminars

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

    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++
    • C++20

    Online Seminars (German)

    Contact Me

    Modernes C++ Mentoring,

     

     

    0 replies

    Leave a Reply

    Want to join the discussion?
    Feel free to contribute!

    Leave a Reply

    Your email address will not be published. Required fields are marked *