Open In App

Concurrency in C++

Last Updated : 10 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Concurrency refers to the ability to process multiple tasks or threads at the same time. It is used to improve the program’s performance and response time. In this article, we will discuss how concurrency is achieved in C++ and what are its benefits.

Concurrency in C++

In C++, the support for concurrency was first added in C++ 11 to improve the performance of the program and enable multitasking. The components such as thread, mutex, memory model, and various synchronization primitives were added as the part of Concurrency Support Library.

Although concurrency provides multitasking, it doesn’t mean that the tasks are executed simultaneously in different processing units. Instead, it works by task switching i.e. doing some task for a small time, then moving to the other tasks, and then coming back again to the first task. It will keep doing it till both of the tasks are done.

In C++, we can achieve concurrency using threads:

Threads in C++

Threads are the basic unit of multitasking. The concurrent execution of the tasks is done by creating multiple threads in a multithreaded environment. The C++ provides a <thread> library for creating and managing threads.

To know more about threads in C++, refer to the article – Multithreading in C++

Errors and Risks Associated with Concurrency

Concurrent multithreading applications need to be carefully designed as it is prone to many errors leading to undefined behaviour. Some of these errors are:

1. Deadlocks

Deadlock refers to the situation where the two or more threads are blocked the forever waiting for the each other. The careful synchronization is essential to the prevent deadlocks.

2. Race Conditions

Race conditions happens when two or more the threads access shared data concurrently leading to the undefined behaviour.

3. Starvation

Starvation is the condition where a thread is unable to the gain regular access to the shared resources.

The above problems can be avoided by proper synchronization between the threads.

Thread Synchronization in C++

Thread synchronization can be done using the following components provided in the C++:

1. Mutex and Locks

The Mutual Exclusion and Locks are used to the protect shared resources. Ensures that only one thread accesses critical sections at a time. C++ have <mutex> header file which contains the std::mutex classes.

To know more about mutex in C++, refer to the article – Mutex in C++

2. Condition Variables

Condition Variables are used for thread synchronization by acting as a flag that notifies the threads when the shared resources are free. It provides a wait-free synchronization in contrast to what mutex and locks do. C++ have <condition_variable> header that contains the condition_variable object.

To know more about condition variable in C++. refer to the article – Condition Variables in C++.

3. Futures and Promises

The <future> and <promise> are used for the asynchronous task execution. This method is only viable when the thread tasks are independent of each other.

4. Semaphores

It is also a synchronization primitive that counts the number of threads accessing the shared resource. If this count exceeds the number of access available, the semaphore will block the access till the count is freed.

Example: Concurrent C++ Program

C++




// C++ Program to illustrate the use of multiple thread
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
using namespace std;
  
// shared resource that will be updated
int sum = 0;
// mutex lock for synchronization (althout application can
// work just fine without it in this case, it is still used
// for demonstration)
mutex lck;
  
// function to get sum of the vector elements in the given
// range
void getSum(const vector<int>& v, int start, int end)
{
    // a predefined wrapper over mutex lock
    lock_guard<mutex> mu(lck);
  
    // performing operation
    for (int i = start; i <= end; i++) {
        sum += v[i];
    }
  
    // mu object will automatically release the mutex lock
    // lck when destroyed
}
  
// driver code
int main()
{
    // vector with 10 elements
    vector<int> v
        = { 2, 4654, 321, 65, 32, 165, 432, 2, 16, 54 };
  
    // finding mid point
    int mid = v.size() / 2;
  
    // creating two threads
    // one thread to add first half elements
    thread t1(getSum, v, 0, mid);
    // other thread to add second half elements
    thread t2(getSum, v, mid + 1, v.size());
  
    // waiting for threads to finish
    t1.join();
    t2.join();
  
    cout << "Array Elements: ";
    for (auto i : v) {
  
        cout << i << " ";
    }
    cout << endl;
  
    // printing sum
    cout << "Sum: " << sum;
  
    return 0;
}


Output

Array Elements: 2 4654 321 65 32 165 432 2 16 54 
Sum: 6048

Concurrency vs Parallelism

The terms concurrency and parallelism are often told as same but there is some difference between them. The below table lists the major differences between the concurrency and parallelism:

Characteristics Concurrency Parallelism
Definition Processing multiple tasks in the overlapping time intervals Simultaneous execution of the multiple tasks on different threads.
Focus Making progress on more than one task at time. Performing multiple tasks at exactly the same time.
Processor Usage Single processor or core at one Multiple processors or cores at once
Task Interaction Tasks may or may not interact with the each other Tasks often work the independently or communicate
Use Cases Suitable and faster for small tasks as it doesn’t have overhead due to being in the single core. Suitable for large tasks for which the thread setup overhead costs is negligible.

Benefits of Concurrency

The concurrency provides a lot of benefits to the programmer and application:

  • Improved Performance: The utilizing multiple CPU cores and executing different parts of your program can improve the performance drastically.
  • Responsiveness: The Applications remain responsive and don’t freeze while performing intensive operations.
  • Resource Utilization: The Efficiently utilize system resources and make the most of the modern multi-core processors.


Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads