引入
在多线程编程中,如何有效地管理对共享数据的访问是提升性能和确保数据安全性的重要课题。C++11及其后续版本引入了 <mutex> 和 <shared_mutex> 头文件,提供了多种不同类型的互斥量,用于处理线程间的同步。其中,C++17 引入的 std::shared_lock 提供了一种灵活的方式,以支持对共享资源的读写操作。std::shared_lock<Mutex>::lock() 用于在使用共享锁时显式地请求占有一个共享锁,让多个线程能够同时读取共享资源,同时又确保在写入时的独占性。这种机制特别适合读多写少的应用场景,提高了数据访问的并发性能。
1. 特性与函数介绍
1.1 特性
- 共享与独占锁的结合:
shared_lock允许多个线程同时获取锁进行读取,从而提升读取性能,同时确保在进行写入时能够独占锁资源。 - 灵活的控制管理:与
std::lock_guard不同,std::shared_lock支持锁定和解锁,以便在不同的代码块之间进行灵活的管理。 - 异常安全:结合 RAII 原则,
shared_lock在作用域结束时会自动释放锁,确保董故撞的情况下锁能及时解锁。
1.2 函数语法
std::shared_lock<Mutex>::lock 方法的基本语法如下:
#include <shared_mutex>
template <class Mutex>
class shared_lock {
public:
shared_lock(Mutex& mutex); // 构造函数,获取共享锁
void lock(); // 获取共享锁
...
};
-
参数:
Mutex& mutex:需要进行共享锁定的互斥量的引用。
-
返回值:无返回值。在成功获取共享锁时不会返回值,如未能获取共享锁,后续逻辑将影响程序的运行和设计。
2. 完整示例代码
以下示例代码展示了如何使用 std::shared_lock<Mutex>::lock 在多线程环境中安全地管理对共享资源的并发访问。
#include <iostream>
#include <thread>
#include <shared_mutex>
#include <vector>
std::shared_mutex st_mutex; // 共享互斥锁
std::vector<int> sharedData; // 共享数据容器
// 读取数据的函数
void readData() {
std::shared_lock<std::shared_mutex> lock(st_mutex); // 获取共享锁
std::cout << "Thread " << std::this_thread::get_id()
<< " reading values: ";
for (const auto& val : sharedData) {
std::cout << val << " "; // 输出共享数据
}
std::cout << std::endl;
// 当 lock 变量超出范围后, 锁会自动解锁
}
// 写入数据的函数
void writeData(int value) {
std::unique_lock<std::shared_mutex> lock(st_mutex); // 获取独占锁
sharedData.push_back(value); // 写入数据
std::cout << "Thread " << std::this_thread::get_id()
<< " wrote value: " << value << std::endl;
// 当 lock 变量超出范围后, 锁会自动解锁
}
int main() {
const int numWriters = 2; // 写线程数量
const int numReaders = 5; // 读线程数量
std::vector<std::thread> writers;
std::vector<std::thread> readers;
// 启动写线程
for (int i = 0; i < numWriters; ++i) {
writers.emplace_back(writeData, (i + 1) * 10); // 传入写入值
}
// 启动读线程
for (int i = 0; i < numReaders; ++i) {
readers.emplace_back(readData);
}
// 等待所有线程完成
for (auto& writer : writers) {
writer.join();
}
for (auto& reader : readers) {
reader.join();
}
return 0;
}
3. 代码解析
-
引入必要的头文件:
- 示例引入了
<iostream>、<thread>、<shared_mutex>和<vector>,以支持多线程、互斥量及动态数组的使用。
- 示例引入了
-
定义共享数据与互斥锁:
std::shared_mutex st_mutex;用于管理对共享数据的访问,同时定义一个std::vector<int> sharedData;作为共享数据存储容器。
-
读取函数:
readData使用std::shared_lock<std::shared_mutex>获取共享锁,并输出多个线程间共享的数据信息,锁在超出作用域后自动解锁。
-
写入函数:
- 在
writeData函数中,通过std::unique_lock<std::shared_mutex>获取独占锁,用于进行数据写入,确保每次只有一个线程能修改数据。
- 在
-
主函数中的线程管理:
- 在
main函数中,创建并启动多个读写线程,最后又使用join()来确保所有线程的执行完成。
- 在
4. 适用场景分析
4.1 读多写少的场景
在许多应用中,读取操作远多于写入,例如配置文件读取、统计信息展示,适合使用 std::shared_lock 增加读取性能。
4.2 实时数据监测
实时数据监测系统中,多个线程获取共享数据以提供更新,利用共享锁实现高并发。
4.3 数据统计及报告生成
在对报告或统计数据输出时,往往会发生多个读取请求,适合使用 shared_lock 确保读取有效性与快速反应。
5. 总结
std::shared_lock<Mutex>::lock 为 C++ 提供了一种灵活且高效的管理共享资源访问机制,允许多个线程同时获取读权限,增强了数据的并发能力。在多线程开发中,合理使用此锁机制有助于提高程序性能和可读性,从而更好地处理复杂场景中的共享数据竞争问题。掌握这一特性将使 C++ 开发者在设计并实现高效且安全的多线程程序时受益匪浅。通过有效运用 std::shared_lock,能够很好地适应现代高负载的计算需求,提升应用系统的响应能力和稳定性。



没有回复内容