在Qt框架中,QReadWriteLock 类提供了读写锁(Read-Write Lock)机制,用于实现高效的多线程同步。读写锁允许多个线程同时读取共享资源,但写操作需要独占访问,从而在读写比例失衡的场景下提升性能。
核心特性
- 共享读锁:多个线程可同时获取读锁(
lockForRead()
),适合读多写少的场景。 - 独占写锁:写锁(
lockForWrite()
)会阻塞所有其他读/写操作,确保数据一致性。 - 可重入性:同一线程可多次获取读锁或写锁,但需配对释放。
- 自动解锁辅助类:
QReadLocker
和QWriteLocker
可自动管理锁的生命周期。
基本用法
1. 头文件引入
#include <QReadWriteLock>
2. 创建读写锁实例
QReadWriteLock rwLock;
3. 读取数据(共享访问)
rwLock.lockForRead(); // 获取读锁
// 安全读取共享数据
rwLock.unlock(); // 手动释放读锁
4. 写入数据(独占访问)
rwLock.lockForWrite(); // 获取写锁
// 安全修改共享数据
rwLock.unlock(); // 手动释放写锁
使用辅助类自动管理锁
推荐使用 QReadLocker
和 QWriteLocker
,它们在作用域结束时自动释放锁,避免忘记解锁。
示例:读操作
{
QReadLocker locker(&rwLock); // 自动获取读锁
// 读取共享数据(如QMap、QVector等)
} // 离开作用域时自动调用 unlock()
示例:写操作
{
QWriteLocker locker(&rwLock); // 自动获取写锁
// 修改共享数据
} // 离开作用域时自动调用 unlock()
注意事项
- 避免死锁:
- 确保锁的获取顺序一致(如全局按资源地址排序)。
- 避免在持有锁时调用可能阻塞的函数。
- 递归锁:
- 同一线程可重复获取读锁或写锁,但需配对释放。
- 例如:获取写锁后,可再次获取读锁,但需先释放写锁。
- 性能权衡:
- 读写锁在“读多写少”场景下效率高,若读写比例接近,
QMutex
可能更简单高效。
- 读写锁在“读多写少”场景下效率高,若读写比例接近,
适用场景
- 共享数据频繁被读取,偶尔被修改(如缓存系统、配置管理)。
- 需要避免
QMutex
在读操作时的竞争开销。
示例代码
#include <QCoreApplication>
#include <QThread>
#include <QReadWriteLock>
#include <QDebug>
class SharedData {
public:
QReadWriteLock lock;
int value = 0;
void read() {
QReadLocker locker(&lock);
qDebug() << "Read:" << value << "Thread:" << QThread::currentThread();
}
void write(int newVal) {
QWriteLocker locker(&lock);
value = newVal;
qDebug() << "Write:" << value << "Thread:" << QThread::currentThread();
}
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
SharedData data;
// 启动多个读线程和一个写线程
for (int i = 0; i < 3; ++i) {
QThread::create([&data]() {
while (true) {
data.read();
QThread::msleep(100);
}
})->start();
}
QThread::create([&data]() {
while (true) {
data.write(qrand() % 100);
QThread::msleep(1000);
}
})->start();
return a.exec();
}
通过合理使用读写锁,可以在保证线程安全的同时,显著提升多线程程序的并发性能。