Qt C++ 读写锁 (QReadWriteLock)
Qt 提供了 QReadWriteLock
类来实现读写锁机制,允许多个线程同时读取数据,但只允许一个线程写入数据。
基本用法
包含头文件
#include <QReadWriteLock>
创建读写锁
QReadWriteLock lock;
读锁定
lock.lockForRead(); // 获取读锁
// 读取共享数据...
lock.unlock(); // 释放锁
写锁定
lock.lockForWrite(); // 获取写锁
// 修改共享数据...
lock.unlock(); // 释放锁
高级用法
使用 QReadLocker 和 QWriteLocker (推荐)
Qt 提供了 RAII 风格的辅助类,可以自动管理锁的生命周期:
QReadWriteLock lock;
// 读锁定
{
QReadLocker locker(&lock);
// 读取共享数据...
} // 自动解锁
// 写锁定
{
QWriteLocker locker(&lock);
// 修改共享数据...
} // 自动解锁
尝试获取锁
if (lock.tryLockForRead(100)) { // 尝试获取读锁,最多等待100毫秒
// 读取数据...
lock.unlock();
} else {
// 获取锁失败
}
if (lock.tryLockForWrite(100)) { // 尝试获取写锁,最多等待100毫秒
// 修改数据...
lock.unlock();
} else {
// 获取锁失败
}
示例代码
#include <QCoreApplication>
#include <QReadWriteLock>
#include <QDebug>
#include <QThread>
class SharedData {
public:
SharedData() : value(0) {}
int getValue() const {
QReadLocker locker(&lock);
return value;
}
void setValue(int newValue) {
QWriteLocker locker(&lock);
value = newValue;
}
private:
int value;
mutable QReadWriteLock lock;
};
class ReaderThread : public QThread {
public:
ReaderThread(SharedData* data) : m_data(data) {}
protected:
void run() override {
for (int i = 0; i < 5; ++i) {
int val = m_data->getValue();
qDebug() << "Reader" << QThread::currentThreadId() << "read value:" << val;
msleep(100);
}
}
private:
SharedData* m_data;
};
class WriterThread : public QThread {
public:
WriterThread(SharedData* data) : m_data(data) {}
protected:
void run() override {
for (int i = 0; i < 5; ++i) {
m_data->setValue(i);
qDebug() << "Writer" << QThread::currentThreadId() << "set value:" << i;
msleep(150);
}
}
private:
SharedData* m_data;
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
SharedData data;
ReaderThread reader1(&data);
ReaderThread reader2(&data);
WriterThread writer(&data);
reader1.start();
reader2.start();
writer.start();
reader1.wait();
reader2.wait();
writer.wait();
return a.exec();
}
注意事项
- 读写锁适用于读多写少的场景
- 写锁会阻塞所有读锁和写锁
- 读锁不会阻塞其他读锁,但会阻塞写锁
- 避免在持有读锁时尝试获取写锁,这可能导致死锁
- 使用 QReadLocker/QWriteLocker 可以避免忘记解锁的问题
- 读写锁比互斥锁(QMutex)有更高的开销,在简单场景下可能性能不如互斥锁
性能考虑
对于高性能场景,Qt 还提供了 QSharedMemory
和 QSystemSemaphore
等更高级的同步机制。