Qt中的读写锁
t中的QReadWriteLock类为我们提供了读写锁的功能。读写锁是用来保护可以被读访问和写访问的资源的一种同步工具。如果你想让多个线程同时的对资源进行读访问,但只要有一个线程要对资源进行写访问时,所有其他的线程必须等待,直到写访问完成。对于这种情况,读写锁是非常有用的。
读写锁的使用也非常简单,如下例子代码所示:
- QReadWriteLock lock;
- void ReaderThread::run()
- {
- ...
- lock.lockForRead();
- read_file();
- lock.unlock();
- ...
- }
- void WriterThread::run()
- {
- ...
- lock.lockForWrite();
- write_file();
- lock.unlock();
- ...
- }
同时,为了确保写操作不会被读操作永远阻塞,当有等待中的写操作时,请求读操作会被阻塞,即使当前的锁由另一个读操作持有。同样,当锁被一个写操作持有时,另一个写操作进来了,那么写操作将会优先于读操作获得锁。
和QMutex一样,QReadWriteLock也可以被同一个线程递归的锁定,只要在构造函数中传入一个QReadWriteLock::Recursive标志。在这种情况下,unlock()被调用的次数必须和lockForWrite()或lockForRead()被调用的次数一样多。但要注意,在一个线程中,递归锁定的类型不能改变,即不能先以读操作上锁,又要以写操作上锁。
同样,为了方便使用QReadWriteLock,Qt还提供了QReadLocker和QWriteLocker两个方便类。能使我们更方便的使用读写锁的功能。即我们可以使用下面这种方式来使用读写锁的功能:
- QReadWriteLock lock;
- QByteArray readData()
- {
- QReadLocker locker(&lock);
- read_file();
- }
- void writeData(const QByteArray &data)
- {
- QWriteLocker locker(&lock);
- write_file();
- }
新建一个Qt控制台程序。在main.cpp中,定义共享数据和读写锁。代码如下:
- #include <QCoreApplication>
- #include <QReadWriteLock>
- #include "readthread.h"
- #include "writethread.h"
- int scores[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
- QReadWriteLock rwLock;
- int main(int argc, char *argv[])
- {
- QCoreApplication a(argc, argv);
- ReadThread readThread[10];
- WriteThread writeThread;
- for(int i = 0; i < 10; i++)
- readThread[i].start();
- writeThread.start();
- for(int i = 0; i < 10; i++)
- readThread[i].wait();
- writeThread.wait();
- return a.exec();
- }
下面,新建出这两个线程,使用QThread类。
其中,读线程的run()函数实现如下:
- extern int scores[10];
- extern QReadWriteLock rwLock;
- void ReadThread::run()
- {
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
- while(true)
- {
- rwLock.lockForRead();
- qDebug() << scores[rand() % 10];
- rwLock.unlock();
- }
- }
读操作,是不断的从数组中随机的读取数据。
- extern int scores[10];
- extern QReadWriteLock rwLock;
- void WriteThread::run()
- {
- qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
- while(true)
- {
- rwLock.lockForWrite();
- scores[rand() % 10] = rand();
- rwLock.unlock();
- sleep(1); //写线程睡眠1s
- }
- }
运行结果如下,大家也可以自行测试: