Skip to main content
C++ Fundamentals for Beginners to Advanced
CHAPTER 24 Beginner

Multithreading in C++

Updated: May 17, 2026
5 min read

# CHAPTER 24

Multithreading in C++

1. Introduction

Historically, programs ran sequentially. Line 1 executes, then Line 2. But modern CPUs have multiple cores. If a game is loading a massive map on one core, the whole game freezes unless it uses another core to keep the UI animated. Multithreading allows your program to do multiple things at the exact same time (Concurrency).

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Understand Threads vs Processes.
  • Create and launch threads using std::thread (C++11).
  • Use join() to wait for threads to finish.
  • Understand Race Conditions.
  • Use std::mutex to synchronize threads and protect shared data.

3. Creating a Thread

Introduced in C++11, the <thread> library makes creating threads incredibly easy. You simply pass a function to a std::thread object.
cpp
12345678910111213141516171819202122232425262728293031323334
#include <iostream>
#include <thread>
#include <chrono> // For sleep
using namespace std;

void task1() {
    for (int i = 0; i < 5; i++) {
        cout << "Task 1 is running..." << endl;
        // Simulate work by sleeping for 100ms
        this_thread::sleep_for(chrono::milliseconds(100)); 
    }
}

void task2() {
    for (int i = 0; i < 5; i++) {
        cout << "Task 2 is running..." << endl;
        this_thread::sleep_for(chrono::milliseconds(100));
    }
}

int main() {
    // Launch threads (they start executing IMMEDIATELY)
    thread t1(task1);
    thread t2(task2);

    // main() continues running...

    // We MUST wait for t1 and t2 to finish before main() exits
    t1.join();
    t2.join();

    cout << "Both tasks finished!" << endl;
    return 0;
}

*Output:* You will see Task 1 and Task 2 printing chaotically mixed together, proving they are running simultaneously!

4. Passing Arguments to Threads

You can pass arguments to the function by simply adding them after the function name in the thread constructor.
cpp
1234567891011
void printMessage(string msg, int count) {
    for(int i=0; i<count; i++) {
        cout << msg << endl;
    }
}

int main() {
    thread t1(printMessage, "Hello from thread!", 3);
    t1.join();
    return 0;
}

5. The Danger: Race Conditions

A Race Condition occurs when two threads try to modify the *same* variable in memory at the exact same time. The result is unpredictable and causes massive bugs.
cpp
12345678910
int shared_counter = 0;

void increment() {
    for (int i = 0; i < 100000; i++) {
        shared_counter++; // DANGER! Not thread-safe!
    }
}

// If t1 and t2 both run increment(), shared_counter will likely NOT be 200,000.
// It might be 145,392 because they overwrote each other's work!

6. The Solution: Mutex (Mutual Exclusion)

A std::mutex is a lock. Before a thread touches a shared variable, it locks the mutex. If another thread tries to access it, it is forced to wait until the first thread unlocks it.
cpp
123456789101112131415161718192021222324252627
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;

int shared_counter = 0;
mutex mtx; // Create a global lock

void increment() {
    for (int i = 0; i < 100000; i++) {
        mtx.lock();   // 1. Lock the door
        shared_counter++; // 2. Safely modify data
        mtx.unlock(); // 3. Unlock the door
    }
}

int main() {
    thread t1(increment);
    thread t2(increment);

    t1.join();
    t2.join();

    // Will now ALWAYS be exactly 200,000!
    cout << "Final counter: " << shared_counter << endl; 
    return 0;
}

*(Note: A safer alternative in modern C++ is std::lockguard<std::mutex> lock(mtx); which automatically unlocks when the function ends, even if an exception is thrown!)*

7. Memory-Level Explanation

  • Processes have separate, isolated memory spaces (Heap, Data, Code).
  • Threads live *inside* a Process. They have their own Stacks, but they share the Heap and Data segments. This is why multithreading is fast (no need to copy memory between processes) but dangerous (race conditions on shared Heap/Global data).

8. Common Mistakes

  • Forgetting join(): If main() reaches return 0; while a thread is still running, the program will crash with a std::terminate error.
  • Deadlocks: Thread A locks Mutex 1 and waits for Mutex 2. Thread B locks Mutex 2 and waits for Mutex 1. Both wait forever. The program freezes entirely.

9. Exercises

  1. 1. Write a program with two threads. One thread prints all even numbers up to 20, the other prints all odd numbers up to 20.
  1. 2. Replace mtx.lock() and mtx.unlock() in the example above with std::lockguard<std::mutex> guard(mtx);.

10. MCQ Quiz with Answers

Question 1

What is the primary benefit of multithreading?

Question 2

Which library is required for modern C++ multithreading?

Question 3

What does t1.join() do?

Question 4

What is a Race Condition?

Question 5

How do you prevent a Race Condition?

Q6. Do threads share the same Heap memory? a) Yes b) No Answer: a) Yes

Q7. Do threads share the same Stack memory? a) Yes b) No, each thread has its own Stack Answer: b) No, each thread has its own Stack

Question 8

What happens if main() finishes before a detached or un-joined thread finishes?

Question 9

What is a Deadlock?

Question 10

How do you pass an argument to a thread?

11. Interview Questions

  • Q: Differentiate between Concurrency and Parallelism.
  • Q: What is a Mutex, and how does it differ from a Semaphore?
  • Q: What is the difference between a Process and a Thread in terms of memory layout?

12. Summary

Multithreading unlocks the full power of modern multi-core CPUs by running tasks concurrently. std::thread makes launching threads easy, but developers must use std::mutex to synchronize access to shared data to prevent race conditions and deadlocks.

13. Next Chapter Recommendation

In Chapter 25: Smart Pointers and Modern C++, we will learn how C++11 revolutionized the language by introducing automatic memory management to prevent memory leaks forever.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·