方法我有一個隊列,其中我可以排隊不同的線程,所以可保證兩件事情:最佳線程同步隊列
- 請求處理一個接一個。
- 請求是在到達的順序處理
第二點是很重要的。否則,一個簡單的關鍵部分就足夠了。 我有不同的要求組,只有在一個組內,這些要點必須得到滿足。來自不同組的請求可以併發運行。
它看起來像這樣:
FTaskQueue.Enqueu('MyGroup');
try
Do Something (running in context of some thread)
finally
FTaskQueue.Dequeu('MyGroup');
end;
編輯:我已刪除的實際執行,因爲它隱藏我想解決
我需要這個,因爲我有一個基於印web服務器的問題接受http請求。首先,我爲請求找到一個相應的會話。然後爲該會話執行請求(代碼)。我可以爲同一個會話獲取多個請求(讀取第一個仍在處理的數據時我可以獲得新的請求),並且它們必須按照正確的到達順序逐個執行。所以我尋求一種通用的同步隊列,可以在這種情況下使用,以便請求可以排隊。我無法控制線程,每個請求都可能在不同的線程中執行。
什麼是最好的(ususal)方法來解決這類問題?問題是Enqueue和Dequeue必須是原子操作才能保證正確的順序。我目前的實施有一個很大的瓶頸,但它的工作。
編輯:貝婁是原子的入隊/出隊操作
你爾德normaly做這樣的事情的問題:
procedure Enqueue;
begin
EnterCriticalSection(FCritSec);
try
DoEnqueue;
finally
LeaveCriticalSection(FCritSec);
end;
BlockTheCurrentThread; // here the thread blocks itself
end;
procedure Dequeue;
begin
EnterCriticalSection(FCritSec);
try
DoDequeue;
UnblockTheNextThread; // here the thread unblocks another thread
finally
LeaveCriticalSection(FCritSec);
end;
end;
現在這裏的問題,這是不是原子。如果你有一個線程已經在隊列中,另一個線程來了並且調用Enqueue,它可能會發生,第二個線程將會離開關鍵部分並嘗試阻塞自己。現在線程調度器將恢復第一個線程,它將嘗試解除阻塞下一個(第二個)線程。但第二個線程還沒有被阻止,所以沒有任何反應。現在第二個線程繼續並阻止自己,但這是不正確的,因爲它不會被解除阻塞。如果阻塞位於關鍵部分內部,那麼臨界部分永遠不會離開,並且我們有一個死鎖。
如果您有多個線程暫停和繼續彼此以確保只有一個線程在任何給定時間執行 - 那麼您應該意識到您的整個設計是錯誤的。在這種情況下,請求不應該等於一個線程。 – mghie 2009-12-07 12:05:09
我懷疑這種方法是不正確的。但讓我們說我有一個Indy服務器。我在Web服務器事件處理程序中獲取http請求。我通過散列表找到一個會話,然後執行請求=爲該會話執行一些代碼。現在,如果在同一個會話中我收到多個請求,他們必須逐一執行。並且每個都將處於不同的線程環境中。我無法控制線程。如果你知道更好的方法,那麼請把它寫成答案。 – Runner 2009-12-07 12:13:45
我明白了,但這些約束根本不可見於您的問題。我認爲,如果您刪除自己的解決方案的細節,只說明問題並尋求解決方法,您會得到更好的答案。 – mghie 2009-12-07 12:20:02