C++
threading
concurrency
programming
tutorial

Simple example of threading in C

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions
markdown
1In modern computing, threading is a fundamental concept that allows a software program to execute multiple operations concurrently within a process. This article explores a simple example of threading in C++, highlighting the intricacies of this powerful feature. We'll cover the basics of threading using the C++ Standard Library and provide insights into common practices and a safety overview.
2
3### Introduction to Threading
4
5Threading enables concurrent execution of parts of a program, known as threads, within a single process. This utilization of concurrency is crucial for performance improvement, particularly in applications such as real-time systems, video games, and software involving complex computations.
6
7### Setting Up the Environment
8
9To explore threading in C++, you need a C++11 compliant compiler, such as GCC 4.8 or newer, Clang 3.3 or newer, or Visual Studio 2013 or newer. This is because C++11 introduced a `std::thread` library offering a standardized way to handle threads.
10
11### Basic Thread Creation Example
12
13In C++, you can initialize a thread by constructing a `std::thread` object. Here's a simple example demonstrating how to create and execute threads:
14
15```cpp
16#include <iostream>
17#include <thread>
18
19// Function that will be executed by a thread
20void threadFunction() &#123;
21    for (int i = 0; i < 5; ++i) &#123;
22        std::cout << "Thread function executing\n";
23    &#125;
24&#125;
25
26int main() &#123;
27    // Create a new thread that runs 'threadFunction'
28    std::thread th(threadFunction);
29
30    // Join the thread with the main thread
31    th.join();
32
33    // Output message from main function
34    std::cout << "Main function executing\n";
35
36    return 0;
37&#125;

Explanation

  1. Thread Function: The threadFunction is a simple routine that outputs a message five times. This represents the task executed by the thread.
  2. Thread Creation and Execution: We create a thread th by passing the threadFunction to the std::thread constructor. This line initializes and begins execution of the thread.
  3. Joining Threads: The th.join() call is crucial. It ensures that the main thread waits for th to complete before exiting. If this step is ignored, the main function may terminate while th is still running, potentially leading to application termination before the thread completes execution.

Key Considerations

  • Thread Safety: When multiple threads access shared data, ensure thread safety by using synchronization mechanisms like mutexes (std::mutex) and condition variables (std::condition_variable). These are required to avoid data races and undefined behavior.
  • Performance: Creating and executing threads has an overhead. Threads should be used judiciously, considering the trade-off between the performance overhead versus improved concurrency.
  • Join vs. Detach: Threads can be detached using th.detach(), allowing them to run independently from the main thread. However, this can lead to undefined behavior if the program ends before the detached thread completes.

Example with Mutex

Consider an advanced example illustrating mutex usage to safely update shared data:

cpp
1#include <iostream>
2#include <thread>
3#include <mutex>
4
5std::mutex mtx;
6int sharedResource = 0;
7
8void incrementResource() &#123;
9    for (int i = 0; i < 100; ++i) &#123;
10        std::lock_guard<std::mutex> lock(mtx);
11        ++sharedResource;
12    &#125;
13&#125;
14
15int main() &#123;
16    std::thread t1(incrementResource);
17    std::thread t2(incrementResource);
18
19    t1.join();
20    t2.join();
21
22    std::cout << "Shared Resource value: " << sharedResource << '\n';
23
24    return 0;
25&#125;

Detailed Explanation

  • Mutex: The std::mutex mtx; declaration provides a mutual exclusion lock. Threads can lock the mutex, ensuring that only one thread accesses sharedResource at a time.
  • Lock Guard: std::lock_guard<std::mutex> lock(mtx); is used to handle the locking automatically. It ensures the mutex is acquired at the lock guard's creation and released when it goes out of scope.
  • Protecting Shared Data: Each increment operation on sharedResource is enclosed within a lock guard, ensuring the resource is safely modified by only one thread at a time.

Summary Table

ConceptDescription
Thread CreationInstantiate std::thread with a function to execute.
Joining ThreadsUse join() to synchronize threads with the main thread.
Detachingdetach() allows independent thread execution.
Thread SafetyUse mutexes to protect shared data.
Lock GuardAutomatically manages mutex locking and unlocking.

Conclusion

This article presented a fundamental look into threading in C++. Utilizing threads can greatly enhance the efficiency and responsiveness of software. However, care must be taken to manage resources appropriately and ensure thread safety. By adhering to best practices and utilizing C++11's std::thread and synchronization tools, developers can harness the power of concurrency effectively.

Understanding these basic principles is essential as developers delve into more complex multithreading scenarios. Each principle forms a building block towards developing reliable, high-performance, multithreaded applications.

 

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.