qt中的线程与线程同步

自定义线程需要继承QThread类并重写run虚函数,这样run函数中的代码就会运行在子线程中。

QThread对象管理着一个线程,并通过start函数启动这个线程

QMutex(互斥锁)

QMutex(互斥锁)提供多线程间串行访问共享资源的方式,本质上的基于互相排斥的锁,

也称为互斥量。

QMutex常用于在多线程中保护对象、数据结果或者代码段,在同一时刻只有一个线程可以拥有互斥量。

--lock():锁定互斥量,如果另外一个线程锁定了这个互斥量,它将阻塞执行直到其他线程解锁这个互斥量。

--unlock():解锁一个互斥量,需要与lock()配对使用

--trylock():试图锁定一个互斥量,如果成功锁定就返回true;如果其他线程已经锁定了这个互斥量,就返回false,但不阻塞程序执行。

QMutexLocker

QMutexLocker是一个简化了互斥量处理的类

QMutexLocker的构造函数接受一个互斥量作为参数并将其锁定,析构函数则将此互斥量解锁,所有在QMutexLocker实例变量的生存期内的代码段得到保护,自动进行互斥量的锁定和解锁。

QMutex互斥量的不足

1.每次只能有一个线程获得互斥量的权限。

2.如果在一个程序中有多个线程读取某个变量,使用互斥量时也必须排队。而实际上若只是读取一个变量,是可以让多个线程同时访问的,这样互斥量就会降低程序的性能。

QReadWriteLock(读写锁)

1.QReadWriteLock以读或写锁定的同步方法允许以读或写的方式保护一段代码

2.可以允许多个线程以只读方式同步访问资源,但是只要有一个线程在以写方式访问资源时,其他线程就必须等待直到写操作结束。

QReadWriteLock提供的主要的函数:

--lockForRead(),以只读方式锁定资源,如果有其他线程以写入方式锁定,这个函数会阻塞;

--lockForWrite(),以写入方式锁定资源,如果本线程或其他线程以读或写模式锁定资源,这个函数就阻塞;

--unlock(),解锁

--tryLockForRead(),是lockForRead()的非阻塞版本

--tryLockForWrite(),是lockForWrite()的非阻塞版本

QWaitCondition(条件等待)

1.QWaitCondition与QMutex结合,可以使一个线程在满足一定条件时通知其他多个线程,使他们及时作出响应,这样比只使用互斥量效率要高一些

2.QWaitCondition一般用于“生产者/消费者”模型中

QWaitCondition提供如下一些函数:

--wait(QMutex *lockedMutex),解锁互斥量lockedMutex,并阻塞等待唤醒条件,被唤醒后锁定lockedMutex并退出函数;

--wakeAll(),唤醒所有处于等待状态的线程,线程唤醒的顺序不确定,由操作系统的调度策略决定;

--wakeOne(),唤醒一个处于等待状态的线程,唤醒哪个线程不确定,由操作系统的调度策略决定

为了描述方便,这里假设主线程(非Qt的UI线程)调用Send()往通信口发送一个数据包,然后阻塞等待回包才继续往下执行。另一个线程(通信线程)不断从通信口中接收数据并解析成数据包,然后唤醒主线程。下面是按网上给的最简单的方法:

// 示例一

// 主线程
Send(&packet);
mutex.lock();
condition.wait(&mutex); 
if (m_receivedPacket)
{
    HandlePacket(m_receivedPacket); // 另一线程传来回包
}
mutex.unlock();


// 通信线程
m_receivedPacket = ParsePacket(buffer);  // 将接收的数据解析成包
condition.wakeAll();

QSemaphore(信号量)

信号量也是一种常用的同步机制,它可以用来控制对共享资源的访问数量。与互斥锁不同,信号量可以允许多个线程同时访问共享资源。

<span style="font-family:Verdana, Geneva, Arial, Helvetica, sans-serif;">#include <QtCore>
 
#include <stdio.h>
#include <stdlib.h>
 
const int DataSize = 100000;
const int BufferSize = 8192;
char buffer[BufferSize];
 
QSemaphore freeBytes(BufferSize);//生产者初始拥有4096B数据缓存区
QSemaphore usedBytes(0);//消费者初始使用了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)  {
        freeBytes.acquire();
        buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4];
        usedBytes.release();
    }//若buffer充满了消费者未读的数据,acquire()就会被阻塞,直到消费者开始消费这些数据
}
 
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();
    }//若buffer没有任何可读数据,acquire()就会被阻塞,直到生产者生产一些数据
    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;
}</span>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值