std::shared_mutex
是 C++17 引入的一个类型,它允许多个线程同时获取共享锁(shared lock),但只允许一个线程独占锁(exclusive lock)。这样,多个线程可以并发地读取共享数据,但在写入数据时,只有一个线程能够独占访问,以保证数据的一致性。
下面是一个使用 std::shared_mutex
的例子:
#include <iostream>
#include <thread>
#include <vector>
#include <shared_mutex>
#include <chrono>
class SharedCounter {
public:
SharedCounter() : count(0) {}
// 读取计数器的值
int get_count() const {
std::shared_lock<std::shared_mutex> lock(mutex_); // 获取共享锁
return count;
}
// 增加计数器的值
void increment() {
std::unique_lock<std::shared_mutex> lock(mutex_); // 获取独占锁
++count;
std::cout << "Counter incremented to " << count << " by thread " << std::this_thread::get_id() << std::endl;
}
// 重置计数器的值
void reset() {
std::unique_lock<std::shared_mutex> lock(mutex_); // 获取独占锁
count = 0;
std::cout << "Counter reset to 0 by thread " << std::this_thread::get_id() << std::endl;
}
private:
mutable std::shared_mutex mutex_; // 使用可变的共享互斥量
int count;
};
// 线程函数,用于增加计数器的值
void increment_counter(SharedCounter& counter, int num_increments) {
for (int i = 0; i < num_increments; ++i) {
counter.increment();
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 暂停一段时间,模拟实际工作
}
}
int main() {
SharedCounter counter;
// 创建多个线程来增加计数器的值
std::vector<std::thread> threads;
for (int i = 0; i < 5; ++i) {
threads.emplace_back(increment_counter, std::ref(counter), 10);
}
// 等待所有线程完成
for (auto& thread : threads) {
thread.join();
}
// 输出最终计数器的值
std::cout << "Final counter value: " << counter.get_count() << std::endl;
// 重置计数器的值
counter.reset();
return 0;
}
在这个例子中,SharedCounter 类有一个 std::shared_mutex 类型的成员 mutex_,用来保护 count 成员变量。increment 和 reset 成员函数使用 std::unique_lock 来获取独占锁,确保在修改 count 时没有其他线程可以访问它。而 get_count 成员函数使用 std::shared_lock 来获取共享锁,允许多个线程同时读取 count 的值。
注意,increment 和 reset 成员函数使用独占锁,是因为这些操作会修改 count 的值,需要保证原子性和数据一致性。而 get_count 成员函数使用共享锁,是因为它只读取 count 的值,不会修改它,因此允许多个线程并发读取。
这个例子展示了 std::shared_mutex 的基本用法,你可以根据实际需求调整线程的数量、操作次数等。同时,请确保理解共享锁和独占锁之间的区别,以及它们如何影响资源的并发访问。