• Qt QReadWriteLock读写锁


    QT中线程间的同步分别有QMutex互斥锁、QSemephone信号量、QWaitCondition条件变量和QReadWriteLock读写锁四种方式。

    这边来介绍的是读写锁,一般应用与具有大量读操作的场景。
    1、读写锁的特性:读共享,写独占。
    读共享 :
    当其他线程占用读锁的时候,如果其他线程请求读锁,会立即获得。
    当其他线程占用读锁的时候,如果其他线程请求写锁,会阻塞等待读锁的释放。
    写独占 :
    当其他线程占用写锁的时候,如果其他线程请求读锁,会阻塞等待写锁的释放。
    当其他线程占用写锁的时候,如果其他线程请求写锁,会阻塞等待写锁的释放。

    2、读写优先级
    默认优先级是写优先,即写锁的优先级>读锁,哪怕是读先排队的也没用。

    3、常用函数包含:
    lockForRead() ; 请求读锁
    lockForWrite() ; 请求写锁
    tryLockForRead() ; 尝试请求读锁,非阻塞函数,可以设置超时时间。
    tryLockForWrite() ; 尝试请求写锁,非阻塞函数,可以设置超时时间。
    unlock() ; 解锁(解读锁和解写锁,均使用该函数)

    4、常关联的类包含:
    QReadLocker;
    QWriteLocker;

    5、例子:

     1 #ifndef WIDGET_H
     2 #define WIDGET_H
     3 
     4 #include <QWidget>
     5 #include <QReadWriteLock>
     6 #include <QReadLocker>
     7 #include <QWriteLocker>
     8 #include <QtWidgets>
     9 #include <QThread>
    10 
    11 class Widget : public QWidget
    12 {
    13     Q_OBJECT
    14 
    15 public:
    16     Widget(QWidget *parent = 0);
    17     ~Widget();
    18     void delay(int msec);
    19 private slots:
    20     void slotStartThread();
    21     void slotReadControl();
    22     void slotWriteControl();
    23 private:
    24     QPushButton* m_readbtn;
    25     QPushButton* m_writebtn;
    26     QPushButton* m_startthreadbtn;
    27     QReadWriteLock m_readWriteLock;
    28 };
    29 
    30 class ReadThread : public QThread
    31 {
    32     Q_OBJECT
    33 public:
    34     ReadThread();
    35     ~ReadThread();
    36     void run();
    37 
    38     void setReadWriteLock(QReadWriteLock &lock);
    39 private:
    40     QReadWriteLock* m_readWriteLock;
    41 };
    42 
    43 class WriteThread : public QThread
    44 {
    45     Q_OBJECT
    46 public:
    47     WriteThread();
    48     ~WriteThread();
    49     void run();
    50 
    51     void setReadWriteLock(QReadWriteLock &lock);
    52 private:
    53     QReadWriteLock* m_readWriteLock;
    54 };
    55 
    56 #endif // WIDGET_H
      1 #include "widget.h"
      2 
      3 Widget::Widget(QWidget *parent)
      4     : QWidget(parent)
      5 {
      6     this->setFixedSize(300,300);
      7 
      8     m_readbtn = new QPushButton("读操作",this);
      9     m_writebtn = new QPushButton("写操作",this);
     10     m_startthreadbtn = new QPushButton("开启线程",this);
     11 
     12     QVBoxLayout* lay = new QVBoxLayout(this);
     13     lay->addWidget(m_startthreadbtn);
     14     lay->addWidget(m_readbtn);
     15     lay->addWidget(m_writebtn);
     16     this->setLayout(lay);
     17 
     18     connect(m_startthreadbtn,SIGNAL(clicked()),this,SLOT(slotStartThread()));
     19     connect(m_readbtn,SIGNAL(clicked()),this,SLOT(slotReadControl()));
     20     connect(m_writebtn,SIGNAL(clicked()),this,SLOT(slotWriteControl()));
     21 
     22 }
     23 
     24 Widget::~Widget()
     25 {
     26 }
     27 
     28 //阻塞延时,用来判断读或者写上锁期间,其它线程的读或者写是否会被阻塞。
     29 void Widget::delay(int msec)
     30 {
     31     QDateTime currentime = QDateTime::currentDateTime();
     32     while (currentime.addMSecs(msec) > QDateTime::currentDateTime())
     33     {
     34     }
     35 }
     36 
     37 void Widget::slotStartThread()
     38 {
     39     for (int i = 0; i < 3; ++i)
     40     {
     41         ReadThread* rthread = new ReadThread();
     42         rthread->setReadWriteLock(m_readWriteLock);
     43         rthread->start();
     44     }
     45 
     46     WriteThread* wthread = new WriteThread();
     47     wthread->setReadWriteLock(m_readWriteLock);
     48     wthread->start();
     49 }
     50 
     51 void Widget::slotReadControl()
     52 {
     53     //测试结果得出,读的时候仍然可以读操作不阻塞,但是读的时候会阻塞写操作。
     54     QReadLocker locker(&m_readWriteLock);
     55     qWarning()<<"main read lock"<<QThread::currentThreadId();
     56     delay(5000);
     57 }
     58 
     59 void Widget::slotWriteControl()
     60 {
     61     //测试结果得出,写的时候无论是读操作还是写操作都会被阻塞。写的时候,排队中的写操作优先级最高,无论是不是后排队的。
     62     QWriteLocker locker(&m_readWriteLock);
     63     qWarning()<<"main write lock"<<QThread::currentThreadId();
     64     delay(5000);
     65 }
     66 
     67 //------------------------read thread--------------------------
     68 ReadThread::ReadThread()
     69 {
     70 
     71 }
     72 
     73 ReadThread::~ReadThread()
     74 {
     75 
     76 }
     77 
     78 void ReadThread::setReadWriteLock(QReadWriteLock& lock)
     79 {
     80     m_readWriteLock = &lock;
     81 }
     82 
     83 void ReadThread::run()
     84 {
     85     while(1)
     86     {
     87         m_readWriteLock->lockForRead();
     88         qWarning()<<"read lock"<<QThread::currentThreadId();
     89         m_readWriteLock->unlock();
     90         QThread::sleep(1);
     91     }
     92 }
     93 
     94 //------------------------write thread--------------------------
     95 
     96 WriteThread::WriteThread()
     97 {
     98 
     99 }
    100 
    101 WriteThread::~WriteThread()
    102 {
    103 
    104 }
    105 
    106 void WriteThread::setReadWriteLock(QReadWriteLock& lock)
    107 {
    108     m_readWriteLock = &lock;
    109 }
    110 
    111 void WriteThread::run()
    112 {
    113     while(1)
    114     {
    115         m_readWriteLock->lockForWrite();
    116         qWarning()<<"write lock"<<QThread::currentThreadId();
    117         m_readWriteLock->unlock();
    118         QThread::sleep(3);
    119     }
    120 }
  • 相关阅读:
    【转】配置BT5中文环境
    Jaspersoft iReport Designer 4.7.0 导出pdf 中文不显示的解决办法
    JS通过get、post向jsp传递中文出现乱码的问题的解决
    从 相机 或者相册 获取图片显示在ImageView 上
    简单几段代码实现窗口抖动
    android 塔防游戏汇总 及android 游戏开发索引
    android 音乐播放器汇总
    android Style应用
    android手机控制电脑源码
    【Android通过手势实现的缩放处理】
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/16170464.html
Copyright © 2020-2023  润新知