【问题标题】:boost condition_variable wait for multiple locksboost condition_variable 等待多个锁
【发布时间】:2014-10-29 10:49:16
【问题描述】:

我无法适应线程编程。我试图用互斥锁和锁构建一个结构。但我需要以两个锁作为参数的 boost::condition_variable::wait 。但是没有两个锁的等待功能。

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

我的目标是

  • 允许同时 add(),将所有内容写入缓冲区
  • 工作线程 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
            ...
        }

    }

【问题讨论】:

  • 请详细说明您的问题:内部缓冲区会发生什么?搜索了吗?何时以及谁使用内部缓冲区中的数据?为什么需要 3 个缓冲区?它提醒了经典的生产者/消费者模式,除了我们没有看到消费者

标签: c++ multithreading boost


【解决方案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);
}

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

【讨论】:

    【解决方案2】:

    您可以在wait 之前和lock 之后手动调用allBufferLock.unlock。但是请注意,如果在其他地方它们也都被锁定,则多个互斥锁的嵌套锁很容易导致死锁。在获得另一个之前解锁一个会更安全,例如如果可能,使用internalBufferLock 而不是allBufferLock。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-22
      • 1970-01-01
      • 2015-01-28
      • 1970-01-01
      • 1970-01-01
      • 2021-07-03
      相关资源
      最近更新 更多