Qt:对于生产者-消费者模式中的消费者来说,这是正确的退出方式吗



制作人:

// it is in the GUI thread
...
MtileLoadQueue.lock();
{
if(!tileLoadQueue.contains(task))
{
MtileToload.lock();
++tilesToload;
MtileToload.unlock();
tileLoadQueue.enqueue(task);
loaderLimit.release();//loaderLimit is a semaphore
}
}
MtileLoadQueue.unlock();

消费者它的子类是QThread:

consumer::run(){
while (!finish)
{
loaderLimit.acquire();//loaderLimit is a semaphore
LoadTask task;
MtileLoadQueue.lock();
{
if (tileLoadQueue.count() > 0)
{
task = tileLoadQueue.dequeue();
}
}
MtileLoadQueue.unlock();
//deal with the task...
Mfinish.lock();
finish = quit; //quit is initialized as false 
Mfinish.unlock();
}
}

当我希望使用者QThread完成它的任务(允许运行函数返回)时,我这样做了(从GUI线程):

Mquit.lock();
quit = true;
Mquit.unlock();
loaderLimit.release();
wait();

然后run()函数可以返回,使用者线程完成它的工作。

这种方法的正确性如何?关于如何退出消费者线程,有没有更好的解决方案,因为我担心退出时是否会出现死锁。

根据队列元素的类型,可以有许多解决方案。

  • 如果元素是指针—nullptr永远不可能是有效对象,那么生产者可能会将nullptr(通常称为中毒对象)添加到队列中,以便通知消费者退出。请注意,如果有许多使用者,则每个使用者必须在退出之前再次将nullptr添加到队列中,以便通知其他使用者。

  • 如果元素是多态对象(指针1或引用),则生产者可以使用poison_task的对象来通知消费者。

  • 如果元素既不是指针也不是多态引用,则:

    • 生产者可以使用sentinel值进行通知
    • 元素类型可以是CCD_ 5,其中空的可选值可以用作毒药对象
    • 元素类型可以是std::pair<bool,T>,其中.first表示.second是有效对象还是毒药。注意,在这种情况下,T必须是默认可构造的

使用任何适合您的情况。

1.注意,在这种情况下,您可以使用nullptr,因为对象是指针

如果工作线程正在轮询状态变量并对其进行评估,是的,这是可能的。然而,GUI线程可以直接设置它:

InstanceOfWorkerThread->m_quit = true; //quit is bad symbol as reserved by QThread itself

这是礼貌地要求线程终止的方式。线程可以忽略"建议"。此外,它只有在下次计算退出变量时才会终止。

您也可以通过调用以下之一来停止线程:

void    QThread::exit ( int returnCode = 0 )
void    QThread::quit ()
void    QThread::terminate ()

最新更新