引入
C++17 标准通过 <mutex> 头文件引入了许多新的功能,以支持多线程编程。在众多新特性中,std::shared_mutex 是一种特殊的互斥量,设计用于支持读写操作的并行性。与传统的互斥量不同,std::shared_mutex 允许多个线程同时读取共享资源,但在写入时则要求独占锁定。std::shared_mutex::lock 方法用于申请写锁,确保只有一个线程能够访问写临界区,从而对共享数据进行修改。学习并理解这一功能,对于设计高性能的多线程程序至关重要。
1. 特性与函数介绍
1.1 特性
- 共享与独占:
std::shared_mutex允许多个线程并发地获取共享锁来读取数据,而独占锁则允许只有一个线程修改数据,简化了读多写少的场景。 - 锁粒度控制:通过写锁与读锁的分开控制,使得程序在高并发情况下能够提高读取性能。
- 适用场景广泛:对于场景中有大量读取操作而较少写入的应用,
std::shared_mutex能显著提升效率。
1.2 函数语法
std::shared_mutex::lock 的基本语法如下:
#include <mutex>
class shared_mutex : public mutex {
public:
void lock(); // 获取独占锁
...
};
- 无参数:该函数调用时不需要传递参数。
- 无返回值:成功获取锁后不会返回任何值。
2. 完整示例代码
以下示例展示了如何使用 std::shared_mutex::lock 在多线程环境中安全地进行写操作。
#include <iostream>
#include <thread>
#include <mutex>
#include <shared_mutex>
#include <vector>
std::shared_mutex smtx; // 定义共享互斥锁
std::vector<int> sharedVector; // 共享数据
// 写操作函数
void writeData(int value) {
smtx.lock(); // 申请独占锁
sharedVector.push_back(value);
std::cout << "Thread " << std::this_thread::get_id()
<< " wrote value: " << value << std::endl;
smtx.unlock(); // 释放锁
}
// 读操作函数
void readData() {
smtx.lock_shared(); // 申请共享锁
std::cout << "Thread " << std::this_thread::get_id()
<< " read values: ";
for (const auto& val : sharedVector) {
std::cout << val << " ";
}
std::cout << std::endl;
smtx.unlock_shared(); // 释放共享锁
}
int main() {
const int numWriteThreads = 3; // 写线程数量
const int numReadThreads = 2; // 读线程数量
std::thread writers[numWriteThreads];
std::thread readers[numReadThreads];
// 启动写线程
for (int i = 0; i < numWriteThreads; ++i) {
writers[i] = std::thread(writeData, i+1);
}
// 启动读线程
for (int i = 0; i < numReadThreads; ++i) {
readers[i] = std::thread(readData);
}
// 等待所有线程完成
for (auto& writer : writers) {
writer.join();
}
for (auto& reader : readers) {
reader.join();
}
return 0;
}
3. 代码解析
-
引入必要的头文件:
- 包含
<mutex>、<thread>和<shared_mutex>,以及标准输入输出库。
- 包含
-
定义共享数据和互斥锁:
- 创建一个
std::shared_mutex smtx用于访问共享数据,定义一个共享的整型向量std::vector<int> sharedVector用于线程间的数据共享。
- 创建一个
-
定义写操作函数:
- 在
writeData函数中,首先请求独占锁,调用smtx.lock(),确保唯一访问共享资源,然后向向量中添加数据,并在完成后释放锁(smtx.unlock())。
- 在
-
定义读操作函数:
- 在
readData函数中,申请共享锁 (smtx.lock_shared()),允许多个线程同时读取共享数据,随后展示向量中的所有内容。最后,释放共享锁 (smtx.unlock_shared())。
- 在
-
主函数中的线程管理:
- 在
main函数中,创建多条线程分别进行写入和读取的操作,并使用join()等待其完成。
- 在
4. 适用场景分析
4.1 读多写少的场景
在需要频繁读取但较少写操作的场景中,std::shared_mutex 尤其有效,可以提高系统在处理读取数据时的性能。
4.2 日志系统或统计管理
在实现日志记录或状态监控的系统中,多个线程可能需要同时读取日志,但写操作相对较少,因此使用共享互斥锁十分合适。
4.3 共享数据库连接
在数据库连接池应用中,多个线程可同时读取连接信息,写操作放在连接创建或释放时,能有效避免资源浪费。
5. 总结
std::shared_mutex::lock 是 C++ 提供的一种重要互斥机制,旨在提高并发程序中读操作的效率。通过允许多个线程共享访问同时对修改操作的独占性质, std::shared_mutex 提供了一种高效的方法来管理共享数据的处理。合理使用这一机制,不仅能够降低由于资源争用导致的性能瓶颈,还能保证数据的一致性与稳定性。掌握这一特性帮助开发者在多线程编程时精确控制资源访问,在性能与安全之间实现良好的平衡。



没有回复内容