QT中 QWaitCondition到底该怎么用?

qt中,多线程同步,该如何实现?使用定时器等待一个预估时间,还是通过信号量来实现?

QTimer

[static] void QTimer::singleShot(int msec, const QObject *receiver, const char *member)

#include 
#include 

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QTimer::singleShot(600000, &app, SLOT(quit()));
    ...
    return app.exec();
}

QDateTime.secsTo

QDateTime start = QDateTime::currentDateTime();
QDateTime now;
do{
    now = QDateTime::currentDateTime();
} while (start.secsTo(now) <= 5);  //5为需要延时的秒数

QWaitCondition

QWaitCondition 用于多线程的同步,一个线程调用QWaitCondition::wait() 阻塞等待,直到另一个线程调用QWaitCondition::wake() 唤醒才继续往下执行。

在处理生产者和消费者线程关系时,建议使用QWaitCondition作为QSemaphore的替代方法,来控制共享或者同步数据。

先看一个不太严谨的例子:

// 生产者线程
sendData(&data);//发送数据给消费者线程
mutex.lock();
condition.wait(&mutex); 
if (m_bReceived)
{
	handlePacket();//处理消费者线程传回的包
}
mutex.unlock();

// 消费者线程
m_bReceived = recvData(buffer);//解析生产者发送过来的数据
condition.wakeAll();

在该例中,主线程(生产者)sendData(&data)给消费者线程发送数据,假设消费者线程收到数据后立马回包(这种情况是可能发生的,因为线程的调度是无序的,所以无法保证主线程总会被优先调度)。此时主线程还未来得及调用 condition.wait(&mutex),消费者线程已经调用了condition.wakeAll(),很显然,这次唤醒是无效的,但主线程继续调用 wait(),然后一直阻塞在那里。

严谨的代码应该是这样的:

// 生产者线程
mutex.lock();
sendData(&data);//发送数据给消费者线程	
condition.wait(&mutex); 
if (m_bReceived)
{
	handlePacket();//处理消费者线程传回的包
}
mutex.unlock();

// 消费者线程
m_bReceived = recvData(buffer);//解析生产者发送过来的数据
mutex.lock();
condition.wakeAll();
mutex.unlock();

主线程中,在发送数据之前先执行mutex.lock(),即使消费者线程收到数据后,也不会立即执行condition.wakeAll()。而是在调用 mutex.lock() 时阻塞住(因为主线程已经把mutex占据上锁了,再尝试上锁就会被阻塞),直到主线程 condition.wait(&mutex)真正执行操作系统的阻塞等待指令并释放mutex,消费者线程的 mutex.lock() 才能出阻塞,继续往下执行,调用 wakeAll(),此时一定能成功唤醒主线程。

小结:通过 mutex 把有严格时序要求的代码保护起来,同时把 wakeAll() 也用同一个 mutex 保护起来,这样能保证:一定先有 wait() ,再有 wakeAll(),不管什么情况,都能保证这种先后关系。

 

 

 

你可能感兴趣的:(Qt,/,Qt,Creator,QTimer,QDateTime,QWaitCondition,QMutex)