Multithreading in C++
# 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::mutexto 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.
*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.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.6. The Solution: Mutex (Mutual Exclusion)
Astd::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.
*(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(): Ifmain()reachesreturn 0;while a thread is still running, the program will crash with astd::terminateerror.
- 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. Write a program with two threads. One thread prints all even numbers up to 20, the other prints all odd numbers up to 20.
-
2.
Replace
mtx.lock()andmtx.unlock()in the example above withstd::lockguard<std::mutex> guard(mtx);.
10. MCQ Quiz with Answers
What is the primary benefit of multithreading?
Which library is required for modern C++ multithreading?
What does t1.join() do?
What is a Race Condition?
How do you prevent a Race Condition?
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
What happens if main() finishes before a detached or un-joined thread finishes?
What is a Deadlock?
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.