Qt多线程编程总结(二)——QMutex
来源:互联网 发布:来访人员软件 编辑:程序博客网 时间:2024/06/10 03:09
QMutex类提供的是线程之间的访问顺序化。
QMutex的目的是保护一个对象、数据结构或者代码段,所以同一时间只有一个线程可以访问它。(在Java术语中,它和同步关键字“synchronized”很相似)。例如,这里有一个方法打印给用户两条消息:
void someMethod() { qDebug("Hello"); qDebug("World"); }
如果同时在两个线程中调用这个方法,结果的顺序将是:
Hello Hello World World
如果你使用了一个互斥量:
QMutex mutex; void someMethod() { mutex.lock(); qDebug("Hello"); qDebug("World"); mutex.unlock(); }
用Java的术语,这段代码应该是:
void someMethod() { synchronized { qDebug("Hello"); qDebug("World"); } }
然后同一时间只有一个线程可以运行someMethod并且消息的顺序也一直是正确的。当然,这只是一个很简单的例子,但是它适用于任何需要按特定频率发生的情况。
但你在一个线程中调用lock(),其它线程将会在同一地点试图调用lock()来阻塞,知道这个线程调用unlock()之后其它线程才会获得这个锁。lock()的一种非阻塞选择是tryLock()。
实验部分:
情形一:
#include <QtCore/QCoreApplication>#include <Qthread>#include <QTextStream>class MyThreadA : public QThread { public: virtual void run(); }; class MyThreadB: public QThread { public: virtual void run(); };int number=6;void MyThreadA::run(){ number *= 5;number /= 4;} void MyThreadB::run(){number *= 3;number /= 2;} int main(int argc, char *argv[]){ QCoreApplication app(argc, argv);MyThreadA a; MyThreadB b; a.run();b.run(); a.terminate();b.terminate();QTextStream out(stdout);out<<number;return app.exec();}
上述代码,很简单,写了两个线程,覆盖了QThread的纯虚函数run(),这两个重构的run方法都是对全局变量number的操作,
主函数中顺序调用这两个方法,a.run()执行后number为7,b.run()执行后为10。
情形二:
#include <QtCore/QCoreApplication>#include <Qthread>#include <QTextStream>class MyThreadA : public QThread { public: virtual void run(); }; class MyThreadB: public QThread { public: virtual void run(); };int number=6;void MyThreadA::run(){ number *= 5;sleep(1);number /= 4;} void MyThreadB::run(){number *= 3;sleep(1);number /= 2;} int main(int argc, char *argv[]){ QCoreApplication app(argc, argv);MyThreadA a; MyThreadB b; a.start();b.start(); a.wait(); b.wait(); QTextStream out(stdout);out<<number;return app.exec();}
运行结果:
number=11;
利用QThread的方法start()同是开启两个线程,值得注意的是wait()函数,不能等待自己,这个是用来多个线程交互的,所以不能当sleep()用。这个函数是在主线程中被调用的时候阻塞了主线程。如果想在外部让子线程暂停,最好的办法是在子线程中设置一个标志,在主线程中更改这个标志,并在子线程的run函数中判断,通过调用其保护函数sleep()来达到暂停的目的了。
查看源代码,即可有清楚的概念:
bool QThread::wait(unsigned long time){ Q_D(QThread); QMutexLocker locker(&d->mutex); if (d->id == GetCurrentThreadId()) { qWarning("QThread::wait: Thread tried to wait on itself"); //当是自身时,直接返回false return false; } if (d->finished || !d->running) //与这个线程对象关联的线程已经结束执行(例如从run函数返回)。如果线程结束返回真值。如果线程还没有开始也返回真值。 return true; ++d->waiters; locker.mutex()->unlock(); bool ret = false; switch (WaitForSingleObject(d->handle, time)) { //调用win的对象处理函数 case WAIT_OBJECT_0: //核心对象被激活,等待成功 ret = true; break; case WAIT_FAILED: qErrnoWarning("QThread::wait: Thread wait failure"); break; case WAIT_ABANDONED: case WAIT_TIMEOUT: default: break; } locker.mutex()->lock(); --d->waiters; if (ret && !d->finished) { //虽然响应成功,但关联对象未结束执行 // thread was terminated by someone else d->terminated = true; QThreadPrivate::finish(this, false); } if (d->finished && !d->waiters) { //关联对象执行结束,并且等待数为零时,关闭句柄。 CloseHandle(d->handle); d->handle = 0; } return ret;}
情形三:(Mutex 作用)
#include <QtCore/QCoreApplication>#include <Qthread>#include <QTextStream>#include <QMutex>class MyThreadA : public QThread { public: virtual void run(); }; class MyThreadB: public QThread { public: virtual void run(); };QMutex mutex;int number=6;void MyThreadA::run(){ mutex.lock();number *= 5;sleep(1);number /= 4;mutex.unlock();} void MyThreadB::run(){mutex.lock();number *= 3;sleep(1);number /= 2;mutex.unlock();} int main(int argc, char *argv[]){ QCoreApplication app(argc, argv);MyThreadA a; MyThreadB b; a.start();b.start(); a.wait(); b.wait(); QTextStream out(stdout);out<<number;return app.exec();}
运行结果:
number=10;
通过实验结果可以看出,QMutex保护了全局变量,同一时间只有一个线程可以访问它。
只得一提的是tryLock()的使用,若以上代码换为mutex.tryLock();那么执行结果可能为11,因为是试图锁定互斥量。如果锁被得到,这个函数返回真。如果另一个进程已经锁定了这个互斥量,这个函数返回假,而不是一直等到这个锁可用为止。
且不能添上sleep()函数,否则提示 "A mutex must be unlocked in the same thread that locked it."的运行错误。
- Qt多线程编程总结(二)——QMutex
- Qt多线程编程总结(二)——QMutex
- Qt多线程编程总结(二)——QMutex
- Qt多线程编程总结(二)——QMutex .
- [转]Qt多线程编程总结(二)——QMutex
- Qt多线程编程(2)——QMutex的使用
- Qt多线程编程: QMutex
- QT——QMutex(互斥量)
- qt QMutex(互斥量)
- Qt线程的简单使用(三)——通过一个实例理解QMutex的使用
- Qt 线程同步(QMutex、QWaitCondition、QSemaphore)
- Qt多线程编程总结(一)
- Qt多线程编程总结(一)
- Qt多线程编程总结(一)
- [转] Qt多线程编程总结(一)
- Qt多线程编程总结(一)
- QT开发(三十四)——QT多线程编程
- Qt多线程编程(1)——多线程演示
- struts2 action中获得HttpServletRequest四种方式
- Flash版同PC版命令的异同点(最新9.83版)
- 接下来得学习计划
- 完全用Linux工作
- I/O端口地址译码
- Qt多线程编程总结(二)——QMutex
- 子目录下也有web.config导致登录时权限错误?
- 实时渲染(第三版):第三章 图形处理单元 3.5 3.6
- 用bash做个tcp客户端
- 俞敏洪的一些话
- 超大型
- 函数指针和指针函数的区别
- C++关于用户输入情况的判定与报错
- 恩和巷6号