2013-07-29 111 views
-1

我想設計一個多線程應用程序,它執行以下操作: 一個線程按順序寫入循環緩衝區。然後將有n個讀寫器線程等待由寫線程發起的某個信號喚醒並從循環緩衝區中讀取。該信號應該以某種方式包含一個整數值,該值表示要讀取的循環緩衝區偏移量。這可能在C++中做到嗎? 任何幫助,將不勝感激。多線程信號

因爲我想要一個能夠儘可能接近高速實時流量的設計,所以我想要消除內存的任何分配/釋放。所以循環隊列將是啓動時分配的連續內存塊。我不確定你提到的排隊是否符合這一點。

生產者只需要跟蹤每次寫入字節時從哪裏開始寫入字節的循環緩衝區數組。 所以我真正要求的是製作者在完成寫入事件時傳播「信號」的方式,該事件包含寫入循環緩衝區的最後一個字節的位置(偏移量)。這將避免需要鎖定機制。

當接收到「傳播」信號/事件時,消費者線程將醒來。他們本身只需要跟蹤他們離開的位置,然後只讀取信號偏移值。最後,生產者和消費者當然需要知道循環緩衝區從何處開始,它有多大,以便他們知道何時進行包裝。

+0

是的,這是可能的。 –

+1

你應該向我們展示你的嘗試,並描述它的行爲如何偏離你的期望。 – andand

回答

0

根據您最近的編輯,我會建議使用有界的隊列。

一個有界的隊列是一個具有特定長度的隊列,因此隊列在開始時被全部分配,並且所有元素都將基於元素的默認構造函數進行初始化,或者爲null,無論您想要什麼它是。

從生產者方面來看:如果隊列未滿,則將一個元素push_back到隊列中。

來自消費者方:如果隊列不爲空,則從隊列中彈出一個元素並處理它。

您不需要通過這種方式在您的生產者和消費者之間發送消息。事實上,讓你的各種線程以某種方式進行溝通會產生很多開銷,而這些開銷只會隨着更多的線程變得更加複雜。

隊列本身需要是線程安全的,並且有關於如何在C++中創建線程安全有界隊列的示例。

編輯:

你可以把你在隊列中呼風喚雨。我會在你的情況下建議一個指針隊列,因爲指針的大小在整個執行過程中將保持不變。這使您可以預先分配隊列,但意味着您必須在運行時分配數據報。

您對線程安全的想法或多或少都是如此。在某些情況下,多線程訪問單個變量是很好的 - 通常在他們不修改變量時,只是讀取它。即使您使用的是循環緩衝區,循環緩衝區也必須是線程安全的,因爲任何兩個生產者或使用者都將更改循環緩衝區。這就是說,每個線程訪問您的循環緩衝區或隊列所需的時間將會非常小 - 它應該有足夠的時間將信息複製到數據結構中或從數據結構中複製出來,就是這樣。您可以在不鎖定其他線程的數據結構的情況下完成對數據的所有其他計算。

如果您想讓多個線程一次訪問數據,您可能需要考慮創建多個隊列或緩衝區。也許每個生產者/消費者對有一個循環緩衝區,或者每個輸入流有一個隊列......無論它發生什麼。沒有更具體的例子很難說。

編輯2

Here's a link to a thread-safe queue。我不確定它是否會有所幫助,但看起來很有希望。

+0

排隊的項目可以是不同的長度,即數據報?另外,從我理解的線程安全意味着一次只有一個線程可以在隊列上運行。儘管有點複雜,但我努力的方法並沒有這種限制。 –

+0

@AlKurlansky我編輯了我的答案。 – Shaz

+0

最後一次交流有很大幫助。有界隊列方法很有意義。現在我需要使用一個等待隊列不爲空的方法的隊列類。一個生產者/一個消費者模型將爲我工作。我不需要在運行時分配數據報。在啓動時,我只需要創建一個大的連續內存塊,然後將數據流傳輸到它,在需要時進行換行等。每個排隊的項目都將指向循環緩衝區中的下一個數據報,並且它們可以處理數據報地點。我可以通過反覆試驗來計算出circ buff的大小。 –

2

這就是國際海事組織,這是一種糟糕的做事方式。讓製作人簡單地將項目添加到循環緩衝區。讓每個閱讀器在循環緩衝區中等待非空。非空時,閱讀器線程只是將下一個項目從緩衝區中移除並進行處理。緩衝區本身應該跟蹤偏移等事情。

至於爲什麼這樣更好:主要是因爲它讓系統的每個部分都可以自己完成自己的事情,並且與系統的其他部分進行最少的交互。

當你描述系統時,生產者需要知道隊列的內部細節,以及消費者線程的基本上所有細節(在任何給定的時間喚醒哪些細節,任何給定的時間,要安排執行任何特定的任務等)

我建議最小化的設計保持生產者致力於生產。它的只有關於系統其餘部分的知識由一件事情組成:一旦產生它們,如何將任務放入隊列中。

同樣,消費者線程只需要知道如何從隊列中獲取任務,以及如何執行該任務。

隊列本身負責所有需要的線程同步。僅當任務從隊列中被移入/移除時才需要同步。隊列本身是相當可重用的(幾乎可以用於這種生產者 - 消費者情況)和可替換的(例如,基於鎖和無鎖實現之間的相當平凡的切換)。

線程調度留給操作系統 - 空閒的使用者線程只需在隊列中等待,然後操作系統決定要喚醒哪一個來執行特定的任務。如果它們當前都不處於空閒狀態,則操作系統也已經「知道」了這一點,並讓它們執行當前處理,直到完成並再次等待隊列。

總結:你的建議使得系統的三個部分都變得更加複雜。更糟糕的是,它與三者交織在一起,所以很難與其中任何一個部分隔離開來。

採用這種設計,在設計的每個部分基本保持簡單,他們每個人都從其他相當孤立,所以每個人都可以從別人的工作,思索,等等,在隔離。

+0

如果你說某件事情是一種糟糕的做事方式,那麼如果你支持這一點並解釋你爲什麼這麼想,那將是有益的。 –