2010-10-13 165 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