Qt中提供了 QReadWriteLock 类,我们可以方便的使用读写锁。
读写锁 是指 读锁 和 写锁 。适用于多个线程读操作比较频繁,而写操作不频繁的场景中。
它能够保证多个线程读操作访问资源时同时进行,而写入操作时阻塞读操作。也就是我们常说的,读共享 和 写独占 。
1. 读共享和写独占
读共享 :
- 当其他线程占用读锁的时候,如果其他线程请求读锁,会立即获得。
- 当其他线程占用读锁的时候,如果其他线程请求写锁,会阻塞等待读锁的释放。
写独占 :
- 当其他线程占用写锁的时候,如果其他线程请求读锁,会阻塞等待写锁的释放。
- 当其他线程占用写锁的时候,如果其他线程请求写锁,会阻塞等待写锁的释放。
2. 读写优先级
Qt的 QReadWriteLock 默认优先级是写优先,即写锁的优先级>读锁。
举个例子,比如当线程A占用写锁的时候,线程B请求读锁,阻塞等待;线程C请求写锁,阻塞等待。那么当线程A释放写锁的时候,此时线程C会占用读写锁,因为写的优先级大于读的优先级。
QReadWriteLock 中常用的函数如下:
- lockForRead() ; 请求读锁
- lockForWrite() ; 请求写锁
- tryLockForRead() ; 尝试请求读锁,非阻塞函数,可以设置超时时间。
- tryLockForWrite() ; 尝试请求写锁,非阻塞函数,可以设置超时时间。
- unlock() ; 解锁(解读锁和解写锁,均使用该函数)
下面为读写锁的简单使用:
读线程:
class ReadThread : public QThread
{
public:
void run(void){
while (1){
// 读锁
readWriteLock.lockForRead();
qDebug() << "Read Thread: " << QThread::currentThreadId() \
<< ", Number is " << g_number;
readWriteLock.unlock();
QThread::msleep(100);
}
}
};
写线程:
class WriteThread : public QThread
{
public:
void run(void){
while (1) {
// 写锁
readWriteLock.lockForWrite();
g_number++;
readWriteLock.unlock();
QThread::msleep(500);
}
}
};
调用部分:
// 创建并开启写入线程
WriteThread writeThread;
writeThread.start();
// 创建并开启读线程
ReadThread readThread[5];
for (int i=0; i<5; ++i)
readThread[i].start();
// 等待线程结束
writeThread.wait();
for (int i=0; i<5; ++i)
readThread[i].wait();
本例子中, g_number 为一个全局变量,是共享资源;启动5个线程读操作,1个线程写操作。每隔500ms进行一次写操作,每个线程每隔100ms进行一次读操作。
同互斥锁(互斥量)一样,读写锁也可以设置 递归锁 或 非递归锁 。当设置为 递归锁 时,只有同线程中所有的锁都被解锁,其他的线程才能够获取该锁。
关于 递归锁 和 非递归锁 的介绍,可以参照: 线程的互斥和同步(8)- C++11中的互斥锁和条件变量
扫描二维码关注公众号,回复:
10083014 查看本文章
同互斥锁一样,提供了互斥锁的管理类: QMutexLocker ;读写锁也提供了,读锁和写锁的管理类:
QReadLocker 和 QWriteLocker :构造时加锁,析构时解锁。这里就不过多的介绍了。
作者:douzhq
个人博客主页:不会飞的纸飞机
文章同步页:线程的互斥和同步(9)- Qt中的读写锁QReadWriteLock