繁体   English   中英

使用boost :: condition_variable的死锁

[英]Deadlock with boost::condition_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对其进行QueueEvent ,它被锁定在boost::lock_guard<boost::mutex> lockEvents(m_mtxEvents);这一行中boost::lock_guard<boost::mutex> lockEvents(m_mtxEvents); 永远。

似乎第一个调用从未释放过lockEvents ,因此所有其他调用都一直在等待释放它。

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

在ThreadProc中,while(ture)循环中,在任何情况下都不会解锁lockEvents。 尝试放锁并在示波器内等待。

在您的代码上有几点要指出:

  1. 您可能希望在调用shutdown之后加入线程,以确保主线程不会在其他线程之前完成。
  2. m_queue.clear(); 关闭时在m_mtxEvents互斥锁之外完成的,这意味着线程安全性不如您想象的那样。
  3. 您对队列的“线程安全处理”应该只是删除一个项目,然后在您去处理事件时释放锁。 您没有明确显示,但是如果不这样做,将导致锁定,从而无法添加项目。

关于这样的线程阻塞的好消息是,您可以轻松地中断并检查其他线程在做什么,然后找到持有该锁的线程。 根据我的第3条评论,可能是您花了很长时间来处理事件。 另一方面,可能是您死锁了。 无论如何,您需要使用调试器来确定您做错了什么,因为您的示例中没有足够的代码来演示您的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM