使用条件变量增强锁定机制

时间:2014-01-13 08:07:10

标签: c++ multithreading boost

所以我有这个代码,这个代码运行良好,但在我看来,我锁定了两次,而且在我看来,如果第一个锁在第二个锁之前再次锁定,我有时会犯错误,在这种情况下,有人可以帮助我更好地理解独特锁的使用吗?什么是在PrepDequeue函数中完全执行的唯一锁定和作用域锁定?

m_mtx = mutable boost :: mutex

m_event = boost :: condition_variable

并且enqueu和dequeue是一些任意队列......

插入功能:

/** : */
void TaskImp::CmdsQueue::Enqueue(Command* cmd)
{
    boost::mutex::scoped_lock guard(m_mtx);
    bool signal = m_enqueue.empty();

    m_enqueue.push_back(cmd);
    if (signal) {
        m_event.notify_one();
    }
}

交换功能(所以出列和排队总是在不同的队列上工作):

/** : */
void TaskImp::CmdsQueue::PrepDequeue(bool wait, size_t ms)
{   
    if (wait) {
        //QueueingMutex_t dummy; once upon a time there was a dummy here
        Timeout timeout(ms);
        boost::unique_lock<boost::mutex> lock(m_mtx); // <=== what is it waiting for?
        if (!m_event.timed_wait(lock, timeout, [this] () {
            return !this ->m_enqueue.empty();
        })) {
            return;
        }
    } 
    boost::mutex::scoped_lock guard(m_mtx); // safe lock? duplicated?
    m_enqueue.swap(m_dequeue);
}

1 个答案:

答案 0 :(得分:0)

拳头我会试着回答你的问题:

  1. PrepDequeue正在为要排队的元素做好准备,当队列为空时似乎wait == true

  2. 由于上一次锁定超出范围,锁定是安全的。

  3. 现在我的想法:

    设计不安全,使用队列就好像它们没有意义一样,只使用一个同步对象同步它们也没有意义。

    更糟糕的是,可能有一个线程而不是运行PrepDequeue的线程,并且该线程可能在调用Dequeue时出现问题,但由于您使用相同的同步对象两个队列,你最终可能会从一个空的队列中尝试pop()

    似乎Enqueue可能会唤醒PrepDequeue

    我的建议:

    1. 仅使用一个队列
    2. Sycnhronize it
    3. 乘坐PrepDequeue
    4. 您可能还想查看此实现:concurrent_queue.hpp