带有boost ::条件_variable的僵局



我有点困扰这个问题,所以这是我的帮助。

我有一个经理,将一些事件推向队列,这是在另一个线程中进行的。我不希望此线程"忙于等待"队列中的事件,因为它可能一直是空的(而且可能总是很满)。另外,我需要m_bShutdownFlag在需要时停止线程。因此,我想在这种情况下尝试condition_variable:如果将某物推到队列,则该线程开始工作。

简化的代码:

class SomeManager {
public:
    SomeManager::SomeManager()
        : m_bShutdownFlag(false) {}
    void SomeManager::Initialize() {
        boost::recursive_mutex::scoped_lock lock(m_mtxThread);
        boost::thread thread(&SomeManager::ThreadProc, this);
        m_thread.swap(thread);
    }
    void SomeManager::Shutdown() {
        boost::recursive_mutex::scoped_lock lock(m_mtxThread);
        if (m_thread.get_id() != boost::thread::id()) {
            boost::lock_guard<boost::mutex> lockEvents(m_mtxEvents);
            m_bShutdownFlag = true;
            m_condEvents.notify_one();
            m_queue.clear();
        }
    }
    void SomeManager::QueueEvent(const SomeEvent& event) {
        boost::lock_guard<boost::mutex> lockEvents(m_mtxEvents);
        m_queue.push_back(event);
        m_condEvents.notify_one();
    }
private:
    void SomeManager::ThreadProc(SomeManager* pMgr) {
        while (true) {
            boost::unique_lock<boost::mutex> lockEvents(pMgr->m_mtxEvents);
            while (!(pMgr->m_bShutdownFlag || pMgr->m_queue.empty()))
                pMgr->m_condEvents.wait(lockEvents);
            if (pMgr->m_bShutdownFlag)
                break;
            else
                /* Thread-safe processing of all the events in m_queue */
        }
    }
    boost::thread m_thread;
    boost::recursive_mutex m_mtxThread;
    bool m_bShutdownFlag;
    boost::mutex m_mtxEvents;
    boost::condition_variable m_condEvents;
    SomeThreadSafeQueue m_queue;
}

但是,当我用两个(或更多)几乎同时呼叫QueueEvent进行测试时,它会永远锁定在boost::lock_guard<boost::mutex> lockEvents(m_mtxEvents);

似乎是第一个电话从未发布lockEvents,所以所有其余的都只是继续等待其释放。

请帮助我找出我在做什么错以及如何解决此问题。

在您的代码上有几件事:

  1. 您可能希望在调用关闭后加入线程,以确保您的主线程在其他线程之前不会完成。
  2. 关闭时的m_queue.clear();在您的m_mtxEvents Mutex锁之外完成,这意味着它不像您想象的那样安全。
  3. 您的队列的"线程安全处理"应只是将项目取下,然后在您下去处理事件时释放锁。您尚未明确显示,但是如果不这样做将导致锁定添加物品的锁。

关于这样的线程阻塞的好消息是,您可以琐碎地打破并检查其他线程在做什么,并找到持有锁定的线程。可能是,根据我的评论#3,您只是花了很长时间来处理活动。另一方面,可能是您有一个死锁。无论如何,您需要使用您的调试器确切地确定您做错了什么,因为您的样本中没有足够的内容来证明您的问题。

螺纹内部,而(ture)循环,无论如何,lockevents都不会解锁。尝试将锁定在范围内等待。

最新更新