`
ydbc
  • 浏览: 766820 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

QT中的多线程(一)

 
阅读更多

QT中的多线程(一)

/************************************华丽丽的分割线*************************************/

这篇文章和以下的一篇文章 QT中的多线程(二)皆为转载文章,文章转自:

http://www.cppblog.com/yuanyajie/archive/2007/08/22/30599.html

十分感谢原文作者,帮我解决了近几日的疑惑,对于QT的线程间的通信有了进一步了解,在这里向他致以我崇高的敬意。

/************************************华丽丽的分割 线*************************************/

QT通过三种形式提供了对线程的支持。它们分别是,一、平台无关 的线程类,二、线程安全的事件投递,三、跨线程的信号-槽连接。这使得开发轻巧的多线程Qt程序更为容易, 并能充分利用多处理器机器的优势。多线程编程也是一个有用的模式,它用于解决执行较长时间的操作而不至于用户界面失去响应。在Qt的早期版本中,在构建库 时有不选择线程支持的选项,从4.0开始,线程总是有效的。

线 程类

Qt 包含下面一些线程相关的类:

QThread 提供了开始一个新线程的方法

QThreadStorage 提供逐线程数据存储

QMutex 提供相互排斥的锁,或互斥量

QMutexLocker 是一个便利类,它可以自动对QMutex加锁与解锁

QReadWriterLock 提供了一个可以同时读操作的锁

QReadLocker与QWriteLocker 是便利类,它自动对QReadWriteLock加锁与解锁

QSemaphore 提供了一个整型信号量,是互斥量的泛化

QWaitCondition 提供了一种方法,使得线程可以在被另外线程唤醒之前一直休眠。

创建一个线程

为创建一个线程,子类化QThread并且重写它的run()函数,例如:

class MyThread : public QThread

{

Q_OBJECT

protected:

void run();

};

void MyThread::run()

{

...

}

之后,创建这个线程对象的实例,调用 QThread::start()。于是,在run()里出现的代码将会在另外线程中被执行。

注 意:QCoreApplication::exec()必 须总是在主线程(执行main()的那个线程)中被调用,不能从一个QThread中调用。在GUI程序中,主线程也被称为GUI线程,因为它是唯一一个 允许执行GUI相关操作的线程。另外,你必须在创建一个QThread之前创建QApplication(or QCoreApplication)对象。

线程同步

QMutex, QReadWriteLock, QSemaphore, QWaitCondition 提供了线程同步的手段。使用线程的主要想法是希望它们可以尽可能并发执行,而一些关键点上线程之间需要停止或等待。例如,假如两个线程试图同时访问同一个 全局变量,结果可能不如所愿。

QMutex 提供相互排斥的锁,或互斥量。在一个时刻至多一个线程拥有mutex,假如一个线程试图访问已经被锁定的mutex,那么它将休眠,直到拥有mutex的 线程对此mutex解锁。Mutexes常用来保护共享数据访问。

QReadWriterLock 与QMutex相似,除了它对 "read","write"访问进行区别对待。它使得多个读者可以共时访问数据。使用QReadWriteLock而不是QMutex,可以使得多线程 程序更具有并发性。

QReadWriteLock lock;

void ReaderThread::run()

{

// ...

lock.lockForRead();

read_file();

lock.unlock();

//...

}

void WriterThread::run()

{

// ...

lock.lockForWrite();

write_file();

lock.unlock();

// ...

}

QSemaphore 是QMutex的一般化,它可以保护一定数量的相同资源,与此相对,一个 mutex只保护一个资源。下面例子中,使用QSemaphore来 控制对环状缓冲的访问,此缓冲区被生产者线程和消费者线程共享。生产者不断向缓冲写入数据直到缓冲末端,再从头开始。消费者从缓冲不断读取数据。信号量比 互斥量有更好的并发性,假如我们用互斥量来控制对缓冲的访问,那么生产者,消费者不能同时访问缓冲。然而,我们知道在同一时刻,不同线程访问缓冲的不同部 分并没有什么危害。

const int DataSize = 100000;

const int BufferSize = 8192;

char buffer[BufferSize];

QSemaphore freeBytes(BufferSize);

QSemaphore usedBytes;

class Producer : public QThread

{

public:

void run();

};

void Producer::run()

{

qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));

for (int i = 0; i < DataSize; ++i) {

freeBytes.acquire();

buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4];

usedBytes.release();

}

}

class Consumer : public QThread

{

public:

void run();

};

void Consumer::run()

{

for (int i = 0; i < DataSize; ++i) {

usedBytes.acquire();

fprintf(stderr, "%c", buffer[i % BufferSize]);

freeBytes.release();

}

fprintf(stderr, "/n");

}

int main(int argc, char *argv[])

{

QCoreApplication app(argc, argv);

Producer producer;

Consumer consumer;

producer.start();

consumer.start();

producer.wait();

consumer.wait();

return 0;

}

QWaitCondition 允许线程在某些情况发生时唤醒另外的线程。一个或多个线程可以阻塞等待一QWaitCondition ,用wakeOne()或wakeAll()设置一个条件。wakeOne()随机唤醒一个,wakeAll()唤醒所有。

下面的例子中,生产者首先必须检查缓冲是否已满(numUsedBytes==BufferSize),如果是,线程停下来等待 bufferNotFull条件。如果不是,在缓冲中生产数据,增加numUsedBytes,激活条件 bufferNotEmpty。使用mutex来保护对numUsedBytes的访问。另外,QWaitCondition::wait()接收一个mutex作为参数,这个mutex应该被调用 线程初始化为锁定状态。在线程进入休眠状态之前,mutex会被解锁。而当线程被唤醒时,mutex会处于锁定状态,而且,从锁定状态到等待状态的转换是 原子操作,这阻止了竞争条件的产生。当程序开始运行时,只有生产者可以工作。消费者被阻塞等待bufferNotEmpty条件,一旦生产者在缓冲中放入 一个字节,bufferNotEmpty条件被激发,消费者线程于是被唤醒。

const int DataSize = 100000;

const int BufferSize = 8192;

char buffer[BufferSize];

QWaitCondition bufferNotEmpty;

QWaitCondition bufferNotFull;

QMutex mutex;

int numUsedBytes = 0;

class Producer : public QThread

{

public:

void run();

};

void Producer::run()

{

qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));

for (int i = 0; i < DataSize; ++i) {

mutex.lock();

if (numUsedBytes == BufferSize)

bufferNotFull.wait(&mutex);

mutex.unlock();

buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4];

mutex.lock();

++numUsedBytes;

bufferNotEmpty.wakeAll();

mutex.unlock();

}

}

class Consumer : public QThread

{

public:

void run();

};

void Consumer::run()

{

for (int i = 0; i < DataSize; ++i) {

mutex.lock();

if (numUsedBytes == 0)

bufferNotEmpty.wait(&mutex);

mutex.unlock();

fprintf(stderr, "%c", buffer[i % BufferSize]);

mutex.lock();

--numUsedBytes;

bufferNotFull.wakeAll();

mutex.unlock();

}

fprintf(stderr, "/n");

}

int main(int argc, char *argv[])

{

QCoreApplication app(argc, argv);

Producer producer;

Consumer consumer;

producer.start();

consumer.start();

producer.wait();

consumer.wait();

return 0;

}

分享到:
评论

相关推荐

    qt 中 多线程tcp通信

    在Qt框架下实现多线程TCP通信是一种常见且高效的方法,尤其在处理实时性要求高、数据量大的网络应用中。以下将详细讲解Qt中如何进行多线程TCP通信,以及涉及的关键知识点。 首先,标题"qt 中 多线程tcp通信"表明...

    基于Qt的多线程并发服务器

    文件列表中的`tcpserver2`可能是一个示例项目或者源代码文件,它展示了如何在Qt环境中实现一个多线程并发服务器的具体细节。通过分析这个文件,你可以更深入地理解如何在实践中应用上述概念。 总的来说,基于Qt的多...

    12.1 Qt5多线程:多线程及简单实例

    Qt5框架提供了一种方便的方式来实现多线程,它允许开发者在不同的线程中执行任务,从而避免主线程(GUI线程)因处理耗时操作而变得卡顿。本知识点将深入探讨Qt5中的多线程以及一个简单的实例——WorkThread。 **1. ...

    QT下多线程 UDP socket示例

    QT下多线程UDP Socket示例是一个典型的网络通信编程应用场景,它涉及到QT库中的网络模块,特别是关于UDP(用户数据报协议)的使用以及多线程技术。在本示例中,开发者创建了一个UDP服务器,该服务器能够在不影响主...

    Qt 多线程访问同一个变量

    在Qt框架中,多线程编程是常见的需求,特别是在处理密集型计算或异步操作时。标题"Qt 多线程访问同一个变量"涉及到的是如何在多线程环境下确保对共享资源(此处为一个全局变量)的安全访问。描述中提到了使用互斥锁...

    qt多线程高效下载文件

    本项目"qt多线程高效下载文件"是基于Qt实现的一个实用工具,它利用多线程技术来提高文件下载的效率,特别是对于大文件或者需要同时下载多个文件的场景,这种多线程策略显得尤为重要。 在HTTP协议方面,它是互联网上...

    基于QT的多线程定时器

    在基于QT的多线程定时器中,可能有一个或多个线程负责定时任务的执行。线程间的通信可以通过信号和槽(Signals & Slots)机制实现,这是QT的一个核心特性,确保了线程安全的数据交换。 3. **QT定时器(QTimer)** ...

    QT中sqlite多线程操作4个注意问题

    ### QT中sqlite多线程操作4个注意问题 在开发基于Qt的应用程序时,经常会遇到需要使用多线程来进行SQLite数据库操作的情况。然而,多线程环境下的数据库操作相较于单线程来说更为复杂,需要特别注意一些细节问题,...

    QT+OPENGL 多线程测试

    QT+OpenGL多线程测试是将高性能图形渲染与Qt框架结合的一种技术应用,它通过利用多线程的优势来提升程序的运行效率。在本项目中,开发者采用了2D纹理贴图的方法,使得图像处理和显示更为高效。接下来,我们将深入...

    Qt Socket 多线程代码实现

    本项目标题为“Qt Socket 多线程代码实现”,是一个适合初学者的示例,它展示了如何使用QtcpSocket在多线程环境中构建一个服务器。下面将详细介绍相关知识点。 首先,我们来理解什么是Socket。Socket是一种在不同...

    qt QTcpServer多线程

    QTcpServer多线程 每个客户端连接的tcpSocket分别分配一个专门的线程来处理。 核心思想:继承并重写QTcpServer的incomingConnection函数去自己实现tcpsocket连接的建立和分配。 incomingConnection函数说明: 当...

    qt5多线程pingIP地址(线程池)

    在本项目中,“qt5多线程pingIP地址(线程池)”是一个利用Qt5框架和多线程技术来实现对多个IP地址进行并发ping操作的应用。这个应用可能会被网络管理员或者开发人员用来快速检测网络连通性,特别是在大规模网络环境...

    Qt多线程通讯

    在“Qt多线程通讯”DEMO中,主线程可能创建了一个`QThread`实例,并启动它。接着,一个工作对象(可能是自定义的QObject派生类)被移动到子线程中。这个工作对象可能会有一个接收参数的槽函数,用于处理主线程传递...

    QT5多线程TCP服务器和客户端demo

    一、QT5中的多线程 在QT5中,QThread类提供了多线程支持。通过继承QThread或者使用 moveToThread() 方法,我们可以将对象移动到新的线程中运行,避免主线程因执行耗时操作而阻塞,提高程序响应性。同时,QThread ...

    Qt 多线程及简单实例 demo

    Qt 多线程及简单实例 demo。 多线程的几大特点: 1.多线程的执行顺序无法保证,与操作系统的调度策略和线程优先级等因素有关。 2.多线程的切换可能发生在任何时刻、任何地点。 3.多线程对代码的敏感度高,因此对...

    QT 多线程TCP服务器与客户端

    QT框架中的多线程TCP服务器与客户端编程是一个关键的领域,尤其在开发高效、响应迅速的网络应用时。本文将深入探讨如何利用QT库,特别是QT5.11.1版本,来构建多线程的TCP服务器和客户端,以及QThread在其中的作用。 ...

    Qt 使用多线程QThread实现进度条

    在Qt框架中,多线程是提升应用程序性能和响应性的重要技术。QThread类是Qt提供的用于线程操作的工具,它使得线程管理变得更加方便,尤其在UI更新和耗时计算任务之间需要分离时。本篇文章将深入探讨如何利用QThread来...

Global site tag (gtag.js) - Google Analytics