2015-06-20 114 views
0

我用C創建了一個線程池。池中的每個線程執行完全相同的功能。多個生產者線程使用相當標準的mutex/cond方法將新數據放入該池的隊列中。任務比較大的線程池

新鮮數據總是相對較大,並具有要被執行的處理量可能需要相當長一段時間。每當我看到像這樣實現的東西時,工作人員會鎖定隊列,同時複製所需的數據或執行他們所請求的任務。在我的情況下,這些操作中的任何一個都可能需要一段時間,並且在那段時間內其他線程將被阻止訪問隊列。

我應該怎樣去宣佈特定線程已經採取了任務,但仍然被用於與任務相關的數據?在隊列中添加某種「進程中」標誌並讓工作線程在其工作時解鎖隊列是否實用?

回答

4

修改隊列結構,這樣什麼排隊僅僅是一個指針數據進行處理。

當一個線程需要抓取一個作業時,它抓住互斥體,獲取下一個指向要執行的任務的指針,可能會跳過指針的隊列副本,或者確保其他線程不會處理它正在處理什麼,然後釋放互斥鎖(或發出一個條件或其他信號)。對大塊數據的訪問是通過指針進行的;只有一個線程有指針;它在完成時會清理乾淨,但是在知道沒有其他線程正在處理相同數據的情況下,它可以安全運行。

所以,你在隊列中不使用它們巧妙的數據大段的問題 - 你使用的數據小塊的,又名一個指向大塊。

目前我隊列爲指針的隊列。但是,在程序開始時,我需要有限數量的緩衝區。糾正我,如果我錯了,但你建議的是,我反而有生產者線程malloc內存按需要,並有工人free它時,他們完成?

我不建議你有生產者使用malloc()和消費者使用free()

什麼我的建議是,你組織隊列,以便沒有任何一個生產者或消費者需要將它鎖定任何時間過長的問題。但是,如果你的隊列已經是一個指針隊列,我不明白你是如何遇到問題的。

它可能歸結爲術語 - 混亂的引發者。

我想說的是,有一個'等待消耗的任務'隊列。有時候,這個隊列將是空的;那麼消費者線程將等待條件'隊列不空',並且當生產者向隊列中添加任務時,其中一個等待消費者將被喚醒並將接管運行新任務。但消費者的第一步只是將任務從「等待被消費」隊列中移除。

有關隊列的信息必須足以確定需要做什麼 - 這可能只是一個指向「任務描述」的指針,它包含指向要存儲數據的更多指針。從隊列中刪除'任務描述'應該(必須)是一個快速,簡單的操作(由互斥和條件保護)。給定的任務描述不會被多個線程同時訪問。它指向的數據不會被其他線程訪問(一般情況下)。如果線程之間共享數據,則必須像往常一樣協調對共享數據的併發訪問。

但是關鍵的設計點是消費者線程在操縱隊列時花費最少的時間阻塞其他消費者線程或生產者線程。它獲得對隊列的訪問權限,刪除隊列中的第一項並釋放對隊列的訪問權限。然後它會繼續處理需要完成的任務 - 不會受到生產者或其他消費者的干擾。同樣,生產者線程準備任務描述並確保使用相關的(預先分配的)緩衝區等 - 仔細處理緩衝區的獲取等。但是當任務描述準備好時,生產者花費非常短的時間獲得對隊列的訪問權限,將任務描述添加到隊列中,釋放對隊列的訪問,發出'隊列不空'狀態的信號。

+0

感謝您的答案喬納森。目前我的隊列是一個指針隊列,但是我在程序開始時malloc有限數量的緩衝區。糾正我,如果我錯了,但你建議的是,我反而有生產者線程malloc內存的要求,並讓工人完成時釋放它? – Jay

+0

@Jay:查看更新。請注意,如果您只是在隊列中有指針,我不確定是否明白是什麼導致了您的問題。您可以將項目添加到隊列中,並儘可能快地從隊列中刪除它們,並根據需要使用互斥鎖和條件變量。你根本不會阻塞隊列。但這就是我在答案的擴展信息中所說的。 –

+0

我相信我的困惑是,一旦工作人員在工作時刪除指向所述緩衝區的任務,我將如何保護生產者的有限數量的緩衝區。我最初認爲應該將這種保護內置到任務隊列中,而應該創建另一個包含空閒緩衝區列表的隊列?在這種情況下,生產者會從空閒緩衝區隊列中彈出下一個清理緩衝區,填充它並將其推送到任務隊列中。工作人員會將其從任務隊列中彈出,然後工作,並在任務完成時將其推送到空閒隊列中。 – Jay