我有一个从main派生的QThread,它正在设备上进行同步读取。读取超时为1000ms。读取被封装在一个永久循环中,并且读取受到QMutex的保护。基本代码是:
线程1-在设备上永远读取
for (;;){
readMutex.lock(); // Lock so that system cannot change device parameters in middle of read
read (&devicePtr, 1000);
readMutex.unlock; //Unlock so that thread 2 can grab lock if its waiting
}
我有另一个在主事件循环下运行的方法,它可以为devicePointer设置一些参数。当设备被读取时,这样做是不安全的,所以它试图获取锁,然后设置参数,然后解锁互斥锁。这将允许线程1读取循环继续进行。基本代码是:
线程2-设置设备参数
void setParm(){
readMutex.lock(); //Expects to take lock as soon as Thread 1 unlocks it
setParam (&devicePtr, PARAM);
readMutex.unlock(); //Unlock so thread 1 can resume its read forever loop
}
我在代码中有一些qDebug,在每个线程获取锁时转储线程id。我看到的是,线程2调用锁并阻塞,而线程1拥有锁并正在进行读取。线程1完成读取并解锁Mutex。线程1继续循环的下一次迭代,并再次获取锁。线程2在readMutex.lock((调用中保持阻塞状态。在线程2最终被允许获取锁并继续之前,这将有5或6次。
我假设QMutex通过循环来对线程进行排队,但线程1能够在下一次迭代中收回锁,情况似乎并非如此。如果在解锁后将QThread::msleep(250(添加到线程1循环的末尾,我可以在某种程度上强制线程2获取锁。睡眠起到了作用,线程2能够立即锁定并设置设备参数。
我做错了什么吗,这是优先考虑的事情吗?知道我如何在不使用msleep将线程1放在后台的情况下通过线程进行循环吗?
没有办法确保调度程序将参与一个或另一个线程。您可以尝试更改正在运行的线程的优先级,以便有更好的机会执行一个线程而不是另一个线程,但这不会保证任何事情,也不是所有系统都支持优先级更改(即:linux不支持(
您应该使用QWaitCondition而不是sleep(您可以将sleep值作为该条件的超时值传递(,并使每个线程在等待该条件(QWaitCcondition::wakeOne(之前唤醒一个等待该条件的挂起线程(QWaidCondition::wait(。