2010-10-13 125 views
15

在VS2010中引入的并发运行时,有一个concurrent_queue类。它有一个非阻塞try_pop()函数。
与英特尔线程构建模块(TBB)类似,从版本2.1升级到2.2时,阻止了pop()调用。为什么concurrent_queue非阻塞?

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

我处于需要阻塞并发队列的情况,而且我不想忙于等待。 除了自己写一个队列,在并发运行时还有另外一种可能吗?

回答

25

a comment from Arch Robison,并没有得到远远超过"horse's mouth"(一)


PPL的concurrent_queue没有阻止弹出,因此同样没有tbb::strict_ppl::concurrent_queue。阻挡弹出窗口可在tbb::concurrent_bounded_queue中找到。

忽略阻塞弹出的设计参数是,在很多情况下,阻塞的同步是在队列外部提供的,在这种情况下,在队列内执行阻塞就成为不必要的开销。

另一方面,旧的tbb::concurrent_queue的阻挡流行音乐在没有外部同步的用户中很受欢迎。

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


的(a)拱是线程构建模块的建筑师。

4

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

0

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

您可以通过使用条件变量或计数信号量或沿着这些行(无论您的特定API提供了什么)来实现所需的功能。你的麻烦不是阻塞/非阻塞;这听起来像一个经典的生产者 - 消费者。

+2

与封'pop',可以实现* *“经典的生产者 - 消费者”大约两行代码使用TBB,而无需编写任何同步原语自己。 (消费者做'while(true)消费(Q.pop());'和生产者'while(true)Q.push(produce());'。)没有阻塞的'pop',同样的问题需要至少两倍的代码:即为每个队列记录一个额外的条件变量。 但是,正如paxdiablo所说,'tbb :: concurrent_bounded_queue'继续提供阻塞'pop'功能,并且基本上是对'concurrent_queue'的一种直接替代。 – Quuxplusone 2012-08-20 23:41:53

2

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

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

在VS2010中你可以使用位于模板类unbounded_buffer中的适当方法来调用enqueue和dequeue。

-Rick