2014-10-29 116 views
2

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

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

我的目标是

  • 允许同时添加(),全部写入缓冲区
  • 工作者线程运算符()(),存储缓冲值
  • 和搜索(),等待在搜索之前的工作线程


    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 
      ... 
     } 

    } 

+0

请详细说明你的问题:是什么内部缓冲区发生?它被搜查?何时和谁使用内部缓冲区中的数据?为什么你需要3个缓冲区?它提醒了古典生产者/消费者模式,除非我们没有看到消费者 – 2014-10-29 11:03:32

回答

0

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

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); 
} 

这是未经测试,但是可以帮助你对你的方式