Open In App

Is std::vector or boost::vector Thread Safe?

Last Updated : 01 Aug, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

In C++, a common question that arises is: Is std::vector or boost::vector thread-safe? The straightforward answer is no, neither std::vector nor boost::vector is thread-safe.

In this article, we will learn why std::vector and boost::vector are not thread-safe and explore some practical alternatives for making them safe to use in a multi-threaded environment.

What is Thread Safety?

Thread safety refers to the property of a program or code segment that ensures correct behavior when accessed from multiple threads simultaneously. A thread-safe component can be used by multiple threads concurrently without causing data races or inconsistent states.

Problems with Thread Safety in std::vector and boost::vector

std::vector is a part of the C++ Standard Library, widely used for dynamic array implementations whereas boost::vector is part of the Boost Libraries, designed to extend the functionalities of the C++ Standard Library. However, both std::vector and boost::vector are not inherently thread-safe.

1. Concurrent Read-Write Access

Simultaneous read and write operations on the same std::vector or boost::vector instance can cause undefined behavior due to data races.

2. Concurrent Write Access

Simultaneous write operations (e.g., modifying, inserting, or deleting elements) are not safe without external synchronization mechanisms.

3. Lack of Built-in Synchronization

Neither std::vector nor boost::vector provides built-in mechanisms to handle concurrent access, which means the user must handle synchronization.

How to Ensure Thread Safety with std::vector and boost::vector

To make std::vector or boost::vector thread-safe, we need to use synchronization mechanisms like mutexes.

For std::vector

We can use a std::mutex to ensure mutual exclusion, which prevents multiple threads from accessing the vector simultaneously. Using this we can protect read and write operations to ensure mutual exclusion.

Example:

C++
// C++ program to demonstrate thread-safe read and write
// operations on a vector using mutexes

#include <iostream>
#include <mutex>
#include <thread>
#include <vector>

// Use the standard namespace
using namespace std;

// Global vector to store integers
vector<int> vec;

// Mutex to protect vector access
mutex vecMutex;

// Function to read elements from the vector
void readVector()
{
    // Lock the mutex to ensure exclusive access
    lock_guard<mutex> guard(vecMutex);

    // Print the elements in the vector
    cout << "Reading from vector: ";
    for (const auto& elem : vec) {
        cout << elem << " ";
    }
    cout << endl;
}

// Function to write elements to the vector
void writeVector()
{
    // Lock the mutex to ensure exclusive access
    lock_guard<mutex> guard(vecMutex);

    // Add elements to the vector
    for (int i = 0; i < 10; ++i) {
        vec.push_back(i);
    }

    // Indicate that writing to the vector is complete
    cout << "Writing to vector completed." << endl;
}

int main()
{
    // Create a thread to read from the vector
    thread t1(readVector);

    // Create a thread to write to the vector
    thread t2(writeVector);

    // Create another thread to read from the vector
    thread t3(readVector);

    // Wait for the first thread to finish
    t1.join();

    // Wait for the second thread to finish
    t2.join();

    // Wait for the third thread to finish
    t3.join();

    return 0;
}


Output

Reading from vector: 
Writing to vector completed.
Reading from vector: 0 1 2 3 4 5 6 7 8 9

For boost::vector

Using boost::vector in a thread-safe manner requires similar synchronization techniques as std::vector, so we can use boost::mutex to ensure thread safety when using boost::vector.

Example:

C++
// C++ program to demonstrate thread safe concurrent
// read/write access to a vector using Boost libraries for
// thread synchronization

// Include necessary Boost headers
#include <boost/container/vector.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>

// Include standard I/O stream header
#include <iostream>

// Use the standard namespace
using namespace std;

// Define a vector using Boost's container library
boost::container::vector<int> vec;

// Define a mutex using Boost's thread library
boost::mutex vecMutex;

// Function to read and print elements from the vector
void readVector()
{
    // Lock the mutex to ensure thread-safe access
    boost::lock_guard<boost::mutex> guard(vecMutex);
    // Print a message indicating the read operation
    cout << "Reading from vector: ";
    // Iterate over elements in the vector and print them
    for (const auto& elem : vec) {
        cout << elem << " ";
    }
    // Print a new line at the end
    cout << endl;
}

// Function to write elements to the vector
void writeVector()
{
    // Lock the mutex to ensure thread-safe access
    boost::lock_guard<boost::mutex> guard(vecMutex);
    // Write numbers 0 to 9 to the vector
    for (int i = 0; i < 10; ++i) {
        vec.push_back(i);
    }
    // Print a message indicating the write operation is
    // complete
    cout << "Writing to vector completed." << endl;
}

// Main function
int main()
{
    // Create three threads to read and write to the vector
    boost::thread t1(readVector);
    boost::thread t2(writeVector);
    boost::thread t3(readVector);

    // Wait for all threads to finish execution
    t1.join();
    t2.join();
    t3.join();

    // Return 0 to indicate successful execution
    return 0;
}


Output

Reading from vector: 
Writing to vector completed.
Reading from vector: 0 1 2 3 4 5 6 7 8 9

Conclusion

Neither std::vector nor boost::vector is inherently thread-safe. To safely use these containers in a multi-threaded environment, we must use external synchronization mechanisms such as std::mutex or boost::mutex to ensure thread safety and to prevent data races for maintaining consistent states when accessing shared data structures concurrently.


Practice Tags :

Similar Reads