In C++, the Standard Template Library (STL) provides some thread-safe containers in the `<mutex>` header to handle concurrent access from multiple threads. These containers ensure that access to shared data is synchronized to avoid data corruption and race conditions. Below are some of the commonly used thread-safe containers in C++:
`std::mutex`:
A mutex (short for mutual exclusion) is not a container but a synchronization primitive that ensures only one thread can access a shared resource at a time. It is the building block for achieving thread safety.
Example:
cpp
#include <iostream>
#include <mutex>
#include <thread>
std::mutex myMutex;
int sharedData = 0;
void incrementSharedData() {
std::lock_guard<std::mutex> lock(myMutex);
// Only one thread can access sharedData at a time
sharedData++;
}
int main() {
std::thread t1(incrementSharedData);
std::thread t2(incrementSharedData);
t1.join();
t2.join();
std::cout << "Shared data after threads: " << sharedData << std::endl;
return 0;
}
`std::shared_timed_mutex`:
This mutex allows multiple threads to share ownership of a resource, with the ability to lock in shared mode (read access) or exclusive mode (write access).
`std::unique_lock`:
A more flexible lock than `std::lock_guard`, `std::unique_lock` allows for manual unlocking and relocking.
- Exclusive access for writing or modifying shared data.
- Only one thread can hold the lock at a time.
- Essential for ensuring data consistency during writing.
`std::shared_lock`:
Similar to `std::unique_lock`, but designed for shared ownership.- Multiple threads can read shared data concurrently.
- No writer is allowed while readers are active.
- Ideal for read-heavy scenarios where multiple threads need frequent access without modification.
`std::deque` with `std::mutex`:
A thread-safe double-ended queue (deque) that provides synchronized access.
Example:
cpp
#include <iostream>
#include <deque>
#include <mutex>
#include <thread>
std::deque<int> myDeque;
std::mutex dequeMutex;
void addToDeque(int value) {
std::lock_guard<std::mutex> lock(dequeMutex);
myDeque.push_back(value);
}
int main() {
std::thread t1(addToDeque, 1);
std::thread t2(addToDeque, 2);
t1.join();
t2.join();
std::cout << "Deque size after threads: " << myDeque.size() << std::endl;
return 0;
}
`std::queue` with `std::mutex`:
A thread-safe queue that provides synchronized access.
`std::map` or `std::unordered_map` with `std::shared_timed_mutex`:
Thread-safe associative containers that allow concurrent read access.
Example:
cpp
#include <iostream>
#include <map>
#include <shared_mutex>
#include <thread>
std::map<int, std::string> myMap;
std::shared_timed_mutex mapMutex;
void addToMap(int key, const std::string& value) {
std::unique_lock<std::shared_timed_mutex> lock(mapMutex);
myMap[key] = value;
}
std::string getFromMap(int key) {
std::shared_lock<std::shared_timed_mutex> lock(mapMutex);
auto it = myMap.find(key);
return (it != myMap.end()) ? it->second : "Not found";
}
int main() {
std::thread t1(addToMap, 1, "One");
std::thread t2(addToMap, 2, "Two");
t1.join();
t2.join();
std::cout << "Value for key 1: " << getFromMap(1) << std::endl;
std::cout << "Value for key 2: " << getFromMap(2) << std::endl;
return 0;
}
These examples provide basic illustrations of using thread-safe containers and synchronization mechanisms in C++. Depending on your specific requirements, you may need to choose the appropriate container and synchronization method to ensure safe concurrent access to shared data.
No comments:
Post a Comment