3.多线程系列文章 之 线程的同步[1/2]
目录
2.1 简介
2.2 Qmutex 应用
2.3 QWaitCondition 应用
接下来继续说线程同步的问题,当n个线程在一起运行时,为了控制其先后运行顺序,或者 对共享数据的访问 ,这就需要用到线程的功能,这仅是我能想到的两个情形.
QT 提供 了QMutex, QReadWriteLock, QSemaphore QWaitCondition 用以提供线程同步.这里就选用QMutex,QWaitCondition 结合一个 “下载工具” 例子 分别讲解说明,其他的以后需用到再说. 如果一篇文章全部讲完,实在够呛,能力有限
2.1 Qmutex 应用
首先我们将使用 QMutex来实现 下载工具 中的 “下载/暂停/停止”三种下载状态切换,以下简称为状态切换。
简单说一下Qmutex,该类是用来同步线程最基础的类。一般通过调用lock /unlock方法.使用Qmutex就是像检测一个标志一样,如果不是true就继续等待,只不过这个等待的过程不会占用cpu时间片。这和循环检测每个标志位有明显的不同。
使用QMutext需要注意的两点是:
1.在同一线程中,Qmutex 不能重复lock或unlock,换句话说就是lock/unlock 只能成对出现。幸好的是如果你不小心这么做的时候,debug时有所提示.
2.线程lock后,只能在同一个线程中进行unlock,例如,A线程lock后,如果企图在B线程直接unlock 来释放,这将会引发错误。
上回讲到线程的控制提到sleep是无法休眠到一半然后唤醒的. 使用Qmutex 可以改变 sleep完全没有回应的局面。在这里我们需要用一个变量做开关,使用Qmutex 做同步访问以达到一种唤醒的效果,也就是我们要做的状态切换了,只不过说法不同。
想象一下该下载工具,为了ui的响应,一般运行时有两个线程.一个是main线程用于gui,另一个是worker线程,用于下载数据,用户随时决定要进行状态切换.
下面是关键的代码部分
#include <QThread> #include <QMutex> class CThread : public QThread { public: CThread(); ~CThread(); public: enum E_downloadState{DS_INIT,DS_START, DS_PAUSE, DS_STOP}; void startDownload(); void pauseDownload(); void stopDownload(); E_downloadState downState() const; protect: void run(); private: QMutex mDownloadMutex; E_downloadState mState; //用于mutex的变量 void setDownloadMutex(bool lock); void setDownState( E_downloadState state); };
画个示意图
开始下载:
暂停下载
中止下载
在这里为了看清整个控制过程,我用qDebug()模拟出下载工具的状态切换