Qt学习:线程的创建和同步

线程:

        一个进程可以分成多个线程,每个线程有自己的Register Set和Stack,但共享进程的Heap、Data、Code (见下图)


创建线程:

       在Qt中要创建线程,第一步是继承QThread类,第二步是实现其中的run()函数,该方法为protected型,由start()函数来调用。下面是例子:

//Producer.h #ifndef PRODUCER_H #define PRODUCER_H #include <QThread> #include <QString> class Producer : public QThread { public: Producer(const QString &prefix); void stopThread(bool isStop); protected: void produceMessage(int x); void run(); private: QString m_prefix ; bool stopThreads ; }; #endif // PRODUCER_H //Producer.cpp #include <QDebug> #include "Producer.h" Producer::Producer(const QString &prefix) : QThread() { m_prefix = prefix; stopThreads = false; } void Producer::stopThread(bool isStop) { stopThreads = isStop; } void Producer::produceMessage(int x) { qDebug() << QString("Producing %1: %2").arg(m_prefix).arg(x); } void Producer::run() { for(int i = 0; !stopThreads; i++) { produceMessage(i); msleep(rand()%3000+1); } } //main.cpp #include <QApplication> #include <QMessageBox> #include <QDebug> #include "Producer.h" bool stopThreads = false; int main(int argc, char *argv[]) { QApplication a(argc, argv); Producer pa("A"); //创建线程对象 Producer pb("B"); pa.start(); // 启动线程 pb.start(); QMessageBox::information( 0, "Threading", "Close me to stop!" ); pa.stopThread(true); pb.stopThread(true); pa.wait(); //等待线程结束 pb.wait(); return 0; }


线程同步:

        多个线程在运行的时候,可以看作是并行的。当线程之间有共享数据时,为了使得数据状态能够保持连贯性而不被破坏,需要使用线程同步来保护某数据或者某段代码(即把某数据的存取或者某段代码的执行由并行变成串行,从而达到保护的目的)。而线程中对数据或代码的保持一般使用“锁”(在QT中叫mutex)来把它们“锁”住,使得在每个时刻这个数据/代码只能被一个线程访问。QT中的mutex使用有下面几种:

  • QMutex
  • QMutexLocker
  • QReadWriteLock
  • QReadLocker / QWriteLocker
  • QSemaphore

//QMutex: 保护lock()与unlock()之间的代码 QMutex mutex; mutex.lock(); //需要保护的代码或数据存取 mutex.unlock(); //QLocker: 保护从QLocker对象创建后的整个函数体内的代码,函数结束后该locker会自动释放“锁” void fun() { QMutexLocker locker(&mutex); //some other code } //QReadWriteLock与QMutex比较相似,不过它提供的函数是:lockForRead()、lockForWrite() //同样,QReadLocker、QWriteLocker与QLocker的使用相似,能够自动释放“锁” //QSemaphore: 上面几种“锁”只能保护一个数据,如果有多个数据要保护,则需要使用QSemaphore QSemaphore s( 10 ); s.acquire(); // s.available() = 9 s.acquire(5); // s.available() = 4 s.release(2); // s.available() = 6 s.release(); // s.available() = 7 s.release(5); // s.available() = 12 s.tryAcquire(15); // s.available() = 12

从上面可以看出:以“Locker”结尾的“锁”用起来更加方便,因为它的对象在销毁时会自动释放锁;而不带"Locker"锁在使用时要注意处理如异常、条件判断等以保证锁能够被释放,否则可能会造成线程“锁”不释放,而被“锁”住的资源/代码不能够被别的线程访问。

你可能感兴趣的:(qt,fun)