線程的互斥和同步(9)- Qt中的讀寫鎖QReadWriteLock

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中的互斥鎖和條件變量

同互斥鎖一樣,提供了互斥鎖的管理類: QMutexLocker ;讀寫鎖也提供了,讀鎖和寫鎖的管理類:
QReadLockerQWriteLocker :構造時加鎖,析構時解鎖。這裏就不過多的介紹了。


作者:douzhq
個人博客主頁:不會飛的紙飛機
文章同步頁:線程的互斥和同步(9)- Qt中的讀寫鎖QReadWriteLock

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