Multi-threading in C/C++
Section 9: Multi-threading in C/C++
Lesson 1: Multithreading Concepts
1.1 Introduction to Multithreading
Multithreading is a programming concept where multiple threads within a process execute independently, sharing the same resources. Threads provide concurrent execution, enhancing program performance and responsiveness.
1.2 Advantages of Multithreading
Parallelism: Concurrent execution of threads allows tasks to run in parallel, utilizing multiple CPU cores.
Responsiveness: Multithreading enhances responsiveness by enabling background tasks to run while the main thread remains interactive.
Resource Utilization: Efficient use of system resources, especially in applications with multiple tasks.
Lesson 2: Basics of Multithreading in C/C++
2.1 Creating Threads
Multithreading in C/C++ involves creating and managing threads using library functions. In C, the pthread library is commonly used.
Example (Creating Threads in C):
#include <stdio.h>
#include <pthread.h>
// Function executed by the thread
void* threadFunction(void* arg) {
printf("Thread is running!\n");
return NULL;
}
int main() {
// Thread identifier
pthread_t threadId;
// Create a thread
int result = pthread_create(&threadId, NULL, threadFunction, NULL);
if (result == 0) {
printf("Thread created successfully!\n");
// Wait for the thread to finish
pthread_join(threadId, NULL);
printf("Thread finished!\n");
} else {
fprintf(stderr, "Failed to create thread!\n");
}
return 0;
}
2.2 Thread Synchronization
Synchronization mechanisms prevent data races and ensure orderly execution of threads. Mutexes and condition variables are commonly used for synchronization.
Example (Mutex for Synchronization in C):
#include <stdio.h>
#include <pthread.h>
// Shared resource
int sharedData = 0;
// Mutex for synchronization
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// Function executed by the thread
void* threadFunction(void* arg) {
for (int i = 0; i < 5; ++i) {
// Acquire the mutex
pthread_mutex_lock(&mutex);
// Modify the shared resource
++sharedData;
printf("Thread: %d\n", sharedData);
// Release the mutex
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main() {
pthread_t threadId;
// Create a thread
int result = pthread_create(&threadId, NULL, threadFunction, NULL);
if (result == 0) {
// Wait for the thread to finish
pthread_join(threadId, NULL);
} else {
fprintf(stderr, "Failed to create thread!\n");
}
return 0;
}
Lesson 3: Synchronization Mechanisms
3.1 Mutexes
Mutexes (Mutual Exclusion) are used to protect shared resources from simultaneous access by multiple threads. They ensure that only one thread can access the critical section at a time.
Example (Mutex Usage in C++):
#include <iostream>
#include <thread>
#include <mutex>
// Shared resource
int sharedData = 0;
// Mutex for synchronization
std::mutex myMutex;
// Function executed by the thread
void threadFunction() {
for (int i = 0; i < 5; ++i) {
// Lock the mutex
std::lock_guard<std::mutex> lock(myMutex);
// Modify the shared resource
++sharedData;
std::cout << "Thread: " << sharedData << std::endl;
}
}
int main() {
std::thread myThread(threadFunction);
// Wait for the thread to finish
myThread.join();
return 0;
}
3.2 Condition Variables
Condition variables are used to synchronize the execution of threads based on certain conditions. They are often used with mutexes to achieve controlled access to shared resources.
Example (Condition Variable in C++):
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
// Shared resource
int sharedData = 0;
// Mutex for synchronization
std::mutex myMutex;
// Condition variable
std::condition_variable myCondition;
// Flag indicating whether the condition is met
bool conditionMet = false;
// Function executed by the thread
void threadFunction() {
for (int i = 0; i < 5; ++i) {
// Lock the mutex
std::unique_lock<std::mutex> lock(myMutex);
// Wait until the condition is met
myCondition.wait(lock, [] { return conditionMet; });
// Modify the shared resource
++sharedData;
std::cout << "Thread: " << sharedData << std::endl;
// Reset the condition
conditionMet = false;
lock.unlock();
myCondition.notify_one();
}
}
int main() {
std::thread myThread(threadFunction);
// Notify the thread that the condition is met
{
std::lock_guard<std::mutex> lock(myMutex);
conditionMet = true;
}
myCondition.notify_one();
// Wait for the thread to finish
myThread.join();
return 0;
}
Understanding multithreading concepts and using synchronization mechanisms like mutexes and condition variables is crucial for developing concurrent and efficient C and C++ programs. Practice creating threads, managing shared resources, and implementing synchronization to build robust multithreaded applications.