boost condition_variable等待多个锁

时间:2014-10-29 10:49:17

标签: c++ multithreading boost

我在习惯线程编程时遇到了问题。我试图用互斥锁和锁来构建一个构造。但我需要boost :: condition_variable ::等待两个锁作为参数。但两个锁没有等待功能。

有没有人给我一个提示,或者我的方法完全错了?

我的目标是

  • 允许同时添加(),将所有内容写入缓冲区
  • 工作线程operator()(),存储缓冲值
  • 和search(),在搜索之前等待工作线程


    class Archive
    {
        vector externalBuffer;
        vector swapBuffer;
        vector internalBuffer;
        boost::mutex externalBufferMutex;
        boost::mutex allBufferMutex;
        boost::condition_variable bufferIsFilledConditionVariable;

        void operator () ()
        {
            unique_lock allBufferLock(allBufferMutex);
            while(true)
            {
                {
                    unique_lock lock(externalBufferMutex);
                    while(buffer.empty())
                    {
                        bufferIsFilledConditionVariable.wait(...); // I should call it with two locks?
                    }
                    externalBuffer.swap(swapBuffer);
                }

                {
                    internalBuffer.swap(swapBuffer);
                    // store values from internalBuffer
                    ...
                    internalBuffer.clear();
                }
            }
        }

        void add(value) // pseudo code here
        {
            {
                lock_guard lock(externalBufferMutex);
                externalBuffer.push_back(value);
            }
            bufferIsFilledConditionVariable.notify_one();
        }

        // search will not be used concurrently with add()
        // it should just wait for the worker thread
        someReturnValue search()
        {
            unique_lock lock(allBufferMutex);
            // search here
            ...
        }

    }

2 个答案:

答案 0 :(得分:1)

我不确定你想要实现的目标,一般来说,你应该避免在多个重叠的锁下操作。

但是,通常,为了避免死锁,您只需使用一致的锁定顺序。非成员lock函数可以帮助解决这个问题:

实施例

unique_lock lk_all(allBufferMutex,      boost::defer_lock);
unique_lock lk_ext(externalBufferMutex, boost::defer_lock);
boost::lock(lk_all, lk_ext);

while(internalBuffer.empty())
{
    lk_all.unlock();
    bufferIsFilledConditionVariable.wait(lk_ext);
    boost::lock(lk_all, lk_ext);
}

这是未经测试的,但可能会帮助您

答案 1 :(得分:0)

您可以在allBufferLock.unlockwait之前手动呼叫lock。但要注意,多个互斥锁的嵌套锁很容易导致死锁,如果在其他地方它们也都会被锁定。在获得另一个之前解锁一个会更安全,例如,如果可能,请internalBufferLock代替allBufferLock