【问题标题】:correct use of boost::wait boost::condition正确使用 boost::wait boost::condition
【发布时间】:2011-07-17 13:53:16
【问题描述】:
boost::condition cond;
boost::recursive_mutex mutex;

for(;;)
{
    D * d = nullptr;

    while( cb.pop(d) ) 
    {

    }

    boost::lock_guard<boost::recursive_mutex> lock( **mutex** );
    cond.wait( **mutex** );
}


while(1)
{
    getchar();

    for( int i = 0 ; i < 1000 ; ++i )
    {
        cb.push(new D(i));           
        boost::lock_guard<boost::recursive_mutex> lock( **mutex** );
        cond.notify_one();
    }
}

我怀疑是互斥体,我只需要互斥体对象?

编辑:

cb 是一个循环缓冲区。 我想实现一种生产者-消费者模式

wait 和 notify_one 是否必须使用相同的互斥锁?

【问题讨论】:

  • 你想做什么?什么是cb?为什么会有这些无限循环?

标签: c++ boost mutex


【解决方案1】:

假设您使用的是最新版本的 boost,boost::conditionboost::condition_variable_any 相同,我认为与 std::condition_variable_any 相同。

如果所有这些都正确,或者至少大致正确,您的代码应该可以编译,但如果您调用 cond.wait(mutex) 并递归锁定 mutex,则可能会死锁。

我建议改为:

boost::condition_variable cond;
boost::mutex mutex;

// In one thread

for(;;)
{
    D * d = nullptr;

    boost::unique_lock<boost::mutex> lock( mutex );
    while( cb.pop(d) ) 
    {

    }
    while (cb.empty())
       cond.wait( lock );
}

// In another thread

while(1)
{
    getchar();

    for( int i = 0 ; i < 1000 ; ++i )
    {
        boost::lock_guard<boost::mutex> lock( mutex );
        cb.push(new D(i));           
        cond.notify_one();
    }
}

如果您的实现支持它,请将std 替换为boost。这个:

  1. 不使用递归互斥锁。确保不要尝试递归锁定它。
  2. 使用互斥锁保护对容器cb的访问。
  3. 在等待期间使用 while 循环来防止虚假唤醒。
  4. 使用更便宜的condition_variable,而不是更昂贵(更灵活)的condition_variable_any。在您的示例中,我没有看到后者的需要。

【讨论】:

  • 您的设计的直接缺点是它会阻止生产者推送而消费者弹出。如果流式算法在 imo 的情况下效率有点低,不是吗?
  • 如果你的cb 不需要被异步访问保护,那么一定要把它从互斥锁的保护下移出来。我不知道你的cb 是否会这样做。我的主要观点是,您不想等待使用 condition_variable_any 的递归锁定互斥锁。
  • 是的确实cb不需要。好的,我会看看condition_variable,谢谢你的回答。哦,最后,boost::recursive_mutex 真的比 boost::mutex 更耗时吗?
  • 这可能取决于平台,答案可能不是真的。但是,condition_variable_any(又名conditioncondition_variable 贵很多。如果您尝试使用除unique_lock&lt;mutex&gt; 以外的任何内容等待它,condition_variable 将在编译时失败。
  • 哦,但是如果你在一个condition_variable_any 上等待一个锁计数大于1 的recursive_mutex,那么你的通知线程将永远无法获得那个recursive_mutex 上的锁.因此你有死锁(无限更多的时间消耗)。
【解决方案2】:

正确 - 你需要一个互斥锁;其目的是确保多个消费者与您的一个生产者同步。

另外,请参阅http://www.boost.org/doc/libs/1_41_0/doc/html/thread/synchronization.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多