通过等待条件等待多个正在运行的线程

Posted

技术标签:

【中文标题】通过等待条件等待多个正在运行的线程【英文标题】:Wait for multiple running threads via waitconditions 【发布时间】:2013-07-16 08:36:47 【问题描述】:

我在使用 qt 同步多个线程时遇到问题(不幸的是 3.3.8)。因为启动线程是一项耗时的任务,所以我想启动一个(工作)线程一次,将其保留在其运行方法中并通知它有关新工作的信息。但我还需要在所有工作完成后同步调用线程中的那些工作线程。

我知道QThread的重载并不是正确使用它,但是在Qt 3.3.8中没有moveToThread-Method所以我不得不这样做。

工作线程类定义如下(简化)

class WorkerThread : public QThread

  private:
    QWaitCondition m_wcNewWork;
    QMutex m_mutexStopped;
    bool m_bStopped; /// Stop thread execution

    void run()
    
        m_mutexStopped.lock();
        while(!m_bStopped)
        
            m_mutexStopped.unlock();    
            m_wcNewWork.wait(); //wait for new work

            msleep(1000); // do something

            //>notify main thread that the work is done<

            m_mutexStopped.lock();
        
        m_mutexStopped.unlock();    
    
  public:
    WorkerThread() : m_bStopped(false) 
    ~WorkerThread()
    
        m_mutexStopped.lock();  
        m_bStopped = true;
        m_mutexStopped.unlock();    
        wait(); // Wait for thread

        //Cleanup       
    
    void startProcessing()
    
        m_wcNewWork.wakeOne(); /// Wakeup thread, since there is something to do        
            

一堆这样的工作线程是在另一个线程中创建的。我们称其为 MainThread。 现在我需要一些东西来通知 MainThread 所有工作线程都已完成工作。我认为 MainThread 中的 WaitConditions 可以解决问题,每个 WorkerThread 都有一个。然后在 MainThread 我写了类似的东西

QWaitCondition waitWorkDone[numWorker];

//Start working
for (int i = 0; i < numWorker; i++)

    WorkerThread[i].setWaitCondition(waitWorkDone);
    WorkerThread[i].startProcessing();


//Wait for all workers to finish their work
for (int i = 0; i < numWorker; i++)

    waitWorkDone[i].wait();

在 WorkerThread::run-method 中,我使用了waitWorkDone.wakeOne() 来通知 MainThread 工作已完成。不幸的是,这不起作用。当 waitWorkDone 在等待之前被唤醒时,MainThread 将永远等待。

所以问题是:我如何同步不离开运行方法的线程?我认为在 Qt 4 中我可以使用线程池来执行此操作,但它们在 Qt 3 中不存在。

提前致谢。

【问题讨论】:

【参考方案1】:

您似乎以错误的方式使用条件变量 (QWaitCondition)。他们需要将它们与互斥锁一起使用才能正常工作,否则唤醒...呼叫可能会丢失,就像这里一样。 您可以修复它们,或者(更简单的方法)只使用信号量来等待工人;工作线程每次递增一次,主线程递减 numWorker 次。

您可以在“PThread Primer”一书中找到关于条件变量的更好解释(非常好的多线程介绍,虽然有些过时)

【讨论】:

感谢您的书籍​​提示。我会看看它。我也有关于 waitcondition::wait-method 中的互斥锁的想法,但我对此感到困惑。如果互斥锁是强制性的,那么没有互斥锁等待的目的是什么? 条件变量和相应的互斥体应该一起工作。当没有人等待相应的条件变量时,互斥锁应该被锁定(这就是为什么等待...函数接受互斥锁),并且当您在没有人等待的条件变量上调用唤醒时,它可能会丢失(这实际上会发生)。跨度>

以上是关于通过等待条件等待多个正在运行的线程的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Linux 上同时等待两个条件?

调用具有条件变量等待的线程对象的析构函数时会发生啥?

在线程中等待标志的最佳方法

在多个等待线程中通知后哪个线程将开始运行[重复]

四十Linux 线程——线程同步之条件变量

java-线程的生命周期