Qt中的讀寫鎖

Qt中的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();
  }


下面我們寫一個例子,來使用以下QReadWriteLock。

新建一個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();
}
此處,我們啓動了10個讀線程,一個寫線程,來模擬多個讀者,一個寫者的情況。

下面,新建出這兩個線程,使用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();
    }
}

讀操作,是不斷的從數組中隨機的讀取數據。


寫線程的run()函數實現如下:

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
    }
}
寫操作,在數組中隨機的寫入一個隨機數。然後睡眠1秒。

運行結果如下,大家也可以自行測試:







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章