Concurrency and Parallelism in C++


Concurrency and parallelism are fundamental concepts in C++ for building efficient and responsive applications. This guide provides an in-depth overview of concurrency and parallelism in C++, along with sample code examples to illustrate these concepts.


1. Concurrency vs. Parallelism

Concurrency is the concept of handling multiple tasks simultaneously, which may not necessarily run in parallel. Parallelism, on the other hand, involves executing tasks in parallel to achieve performance improvements. C++ provides various mechanisms to support both concurrency and parallelism.


2. Threading in C++

C++ offers a threading library that enables developers to create and manage threads. The std::thread class is commonly used for this purpose. Here's a sample code illustrating the creation of two threads:


#include <iostream>
#include <thread>
void ThreadFunction(int threadId) {
std::cout << "Thread " << threadId << " is running." << std::endl;
}
int main() {
std::thread t1(ThreadFunction, 1);
std::thread t2(ThreadFunction, 2);
t1.join(); // Wait for thread t1 to finish
t2.join(); // Wait for thread t2 to finish
std::cout << "All threads have completed." << std::endl;
return 0;
}

3. Parallelism with Parallel Algorithms

C++17 introduced parallelism support through parallel algorithms in the Standard Template Library (STL). These algorithms can execute operations on containers in parallel, taking advantage of available hardware cores. Here's an example using std::for_each in parallel:


#include <iostream>
#include <vector>
#include <algorithm>>
#include <execution>>
int main() {
std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::for_each(std::execution::par, data.begin(), data.end(), [](int& element) {
element *= 2;
});
for (const int& value : data) {
std::cout << value << " ";
}
return 0;
}

4. Synchronization and Thread Safety

When working with multiple threads, proper synchronization is essential to prevent data races and ensure thread safety. C++ provides synchronization primitives like std::mutex and std::atomic to coordinate thread execution and access to shared resources.


Sample Code: Synchronization with Mutex

Here's a code example demonstrating the use of a mutex to protect a shared resource:


#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
int sharedData = 0;
void ModifySharedData() {
std::lock_guard<std::mutex> lock(mtx);
sharedData++;
}
int main() {
std::thread t1(ModifySharedData);
std::thread t2(ModifySharedData);
t1.join();
t2.join();
std::cout << "Shared data value: " << sharedData << std::endl;
return 0;
}

5. Conclusion

Concurrency and parallelism are essential for achieving optimal performance and responsiveness in C++ applications. By understanding these concepts and employing the appropriate C++ features, developers can harness the power of multi-core processors and create efficient software.