Is std::vector or boost::vector Thread Safe?
Last Updated :
01 Aug, 2024
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.
Similar Reads
What is thread safe or non-thread safe in PHP ?
Thread-safe: It is used to ensure that when the shared data structure which is manipulated by different threads are prevented from entering the race condition. Thread-safety is recommended when the web server run multiple threads of execution simultaneously for different requests. In Thread Safety b
2 min read
Vector of Vectors in C++ STL with Examples
In C++, a vector of Vectors is a two-dimensional vector with a variable number of rows, where each row is a vector. Each index of a vector stores a vector that can be traversed and accessed using iterators. It is similar to an Array of Vectors but with dynamic properties. Syntax:C++vector<vector
4 min read
Difference between std::remove and vector::erase for vectors
std::remove : It doesn't actually delete elements from the container but only shunts non-deleted elements forwards on top of deleted elements. vector::erase : Removes from the vector either a single element (position) or a range of elements ([first, last)). std::remove vs vector::erase By using eras
4 min read
Is std::vector So Much Slower Than Plain Arrays?
In C++, std::vector is a dynamic array provided by the Standard Template Library (STL), and it is commonly compared to plain arrays. A frequent question that arises is: Is std::vector significantly slower than plain arrays? The straightforward answer is no, std::vector is not significantly slower, t
6 min read
Problem With std::vector<bool> in C++
In C++ STL, we have a std::vector container that works in the same way as dynamic arrays. However, the specialized implementation of std::vector<bool> has several complications, including performance issues, indirect access, and difficulties with standard algorithms.In this article, we will le
4 min read
C++ STL - Vector in Reverse Order
Prerequisite: Vectors in C++ A vector can be printed in reverse order with the following methods: By traversing in the backward direction using indexingBy traversing in the backward direction using begin() and end() functions in C++ STLBy traversing in the backward direction using rbegin() and rend(
3 min read
When to use Vector reserve() in C++?
In a vector, when the number of elements to be inserted are greater than the current capacity, it is reallocated to a larger memory block and all the items are copied to this new block making this reallocation an expensive operation with time complexity of O(n).This mechanism works well if you don't
2 min read
vector :: cbegin() and vector :: cend() in C++ STL
Vectors are known as dynamic arrays which can change its size automatically when an element is inserted or deleted. This storage is maintained by container. vector::cbegin() The function returns an iterator which is used to iterate container. The iterator points to the beginning of the vector.Iterat
2 min read
unordered set of Vectors in C++ with Examples
What is an unordered set? In C++, an unordered set is an unordered container that can hold a number of unique elements. Unlike a set, elements in an unordered set are not arranged in any particular order. Internally, an unordered set is implemented using a hash table where keys are hashed into indic
6 min read
Copy File To Vector in C++ STL
Prerequisite:Â Vectors in C++ STLFile Handling in C++ The C++ Standard Template Library (STL) provides several useful container classes that can be used to store and manipulate data. One of the most commonly used container classes is the vector. In this article, we will discuss how to copy the conte
2 min read