【问题标题】:why is concurrent_queue non-blocking?为什么 concurrent_queue 是非阻塞的?
【发布时间】:2011-04-24 21:37:16
【问题描述】:

在VS2010引入的并发运行时,有一个concurrent_queue类。它有一个非阻塞的 try_pop() 函数。
与 Intel Thread Building Blocks (TBB) 类似,从 2.1 版升级到 2.2 版时,阻塞的 pop() 调用已被移除。

我想知道阻塞调用有什么问题。为什么从 TBB 中删除?还有为什么没有阻塞concurrent_queue?

我处于需要阻塞并发队列的情况,并且我不想忙于等待。 除了自己写队列,并发运行时是否还有其他可能?

【问题讨论】:

    标签: c++ concurrency queue


    【解决方案1】:

    来自a comment from Arch Robison,并没有比"horse's mouth"得到更多(a)


    PPL 的concurrent_queue 没有阻塞弹出,因此tbb::strict_ppl::concurrent_queue 也没有。阻止弹出在tbb::concurrent_bounded_queue 中可用。

    省略阻塞弹出的设计论据是,在许多情况下,阻塞的同步是在队列外部提供的,在这种情况下,在队列内部实现阻塞就变成了不必要的开销。

    另一方面,旧的tbb::concurrent_queue 的阻塞弹出在没有外部同步的用户中很受欢迎。

    所以我们拆分了功能。不需要阻塞或有界的用例可以使用新的tbb::concurrent_queue,而确实需要它的用例可以使用tbb::concurrent_bounded_queue


    (a) Arch 是 Threading Building Blocks 的架构师。

    【讨论】:

      【解决方案2】:

      如果您需要一个没有繁忙等待的阻塞弹出,您需要一种信号方法。这意味着 pusher 和 poper 之间的同步,并且队列不再没有(昂贵的)同步原语。你基本上得到了一个正常的同步队列,其中一个条件变量用于通知 poppers 推送,这不是 concurrent_* 集合的精神。

      【讨论】:

        【解决方案3】:

        问题是并发运行时是否有另一个选项提供阻塞队列功能,因为 concurrent_queue 没有,而在 VS2010 中有一个。

        Arch 的评论当然是完全正确的,阻塞队列和解除阻塞队列是不同的用例,这就是它们在 VS2010 和 TBB 中不同的原因。

        在VS2010中可以使用位于的模板类unbounded_buffer,相应的方法称为入队和出队。

        -瑞克

        【讨论】:

          【解决方案4】:

          从队列的角度来看,没有任何情况应该需要阻塞插入或删除。您可能需要阻止并等待插入这一事实并不重要。

          您可以通过使用条件变量、计数信号量或类似的东西(无论您的特定 API 提供什么)来实现您想要的功能。您的麻烦不在于阻塞/非阻塞;听起来像是典型的生产者-消费者。

          【讨论】:

          • 通过阻塞pop,您可以在大约两行代码中使用TBB实现“经典生产者-消费者”,而无需自己编写任何同步原语。 (消费者执行while (true) consume(Q.pop());,生产者执行while (true) Q.push(produce());。)如果没有阻塞pop,同样的问题需要至少两倍的代码:即,为每个队列记录一个额外的条件变量。但正如 paxdiablo 所说,tbb::concurrent_bounded_queue 继续提供阻塞 pop 功能,基本上是 concurrent_queue 的替代品。
          猜你喜欢
          • 1970-01-01
          • 2012-10-31
          • 2020-12-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-11-06
          • 2017-04-26
          • 2018-11-15
          相关资源
          最近更新 更多