Programming in C++

Concurrency

Overview

Gerald Senarclens de Grancy

Concurrency

Definition

  • Ability of a program to be decomposed into parts that can run out of order or in partial order without affecting the final outcome
  • Composition of independently executing tasks
  • Concurrency is about managing multiple tasks, not speed
  • On a single CPU core, only one task executes at any given moment

Multiple tasks start, run, and complete in overlapping time periods

Time-slicing
On a single-core processor, the CPU switches back and forth between tasks so fast it seems like they are happening at the same time
graph LR
  T1[Task A
Part 1] --> T2[Task B
Part 1] T2 --> T3[Task A
Part 2] T3 --> T4[Task C
Part 1] T4 --> T5[Task B
Part 2] T5 --> | ... | T6[End] style T1 fill:#f9f style T2 fill:#ccf style T3 fill:#f9f style T4 fill:#ff9 style T5 fill:#ccf
Conceptual Timeline (Single Core)

Concurrency is a high-level concept

Multithreading

Multithreading is a specific way to achieve concurrency using a single process

Example - Mobile Application

Task 1
Listening for touch inputs
Task 2
Fetching data from an API
Task 3
Updating a progress bar

If the tasks weren't structured concurrently,
the app would "freeze" while waiting for data

Race Condition

All threads within a process share the same memory space

This makes communication fast, but risky:
multiple threads might change the same variable "at once"

sequenceDiagram
    autonumber
    actor T1 as Thread 1
    participant Mem as Shared Memory
(counter = 10) actor T2 as Thread 2 Note over T1, T2: Goal: Both threads increment 'counter' %% --- The Intersection --- activate T1 Note right of T1: Step 1: READ Mem->>T1: Load counter (10) into Register A activate T2 Note left of T2: Step 2: READ (T2 runs before T1 writes) Mem->>T2: Load counter (10) into Register B Note left of T2: Step 3: INCREMENT Reg B = 11 Note left of T2: Step 4: WRITE (T2 overwrites T1's work) T2->>Mem: Store Register B (11) Note right of T1: Step 5: INCREMENT Reg A = 11 %% --- The Collision --- Note right of T1: Step 6: WRITE T1->>Mem: Store Register A (11) deactivate T1 deactivate T2 Note over T1, T2: Result: RACE CONDITION (Data Loss: counter = 11, expected: 12)

Multiprocessing

Multiprocessing is about parallel computing to improve performance (true parallelism)

It requires using two or more CPU cores to execute tasks simultaneously

Each process has its own private memory space and processes communicate via message passing

If one process crashes, the remaining processes can continue

Mini-example: make -j8 compiles up to 8 source files in parallel

Example: Modern Web Browsers

Modern browsers like Firefox moved to a Multi-Process Architecture

  • The browser window and each individual tab are separate processes
  • If a tab's process crashes, other tabs and the main window stay alive
  • This also improves security (each tab has its own private memory space)

However, even though each tab uses its own process, each of those processes is still heavily multithreaded

Summary

Multithreading Multiprocessing
Execution one or more CPU cores multiple CPU cores
Memory shared separate
Applications responsive UIs CPU-heavy computations
Issues race conditions communication overhead

Use multithreading to "wait" for network responses or a database

Use multiprocessing for CPU heavy computations (eg. video encoding)

Questions
and feedback...