2010-07-01 233 views

回答

7

是的,異步請求通常可以在不花費線程的情況下處理。操作系統對它們有特殊的支持,如重疊的I/O和完成端口等功能。他們實際上做的是利用內核線程的代價,無論如何,因爲驅動程序需要能夠處理來自多個用戶模式程序的多個請求。 .NET框架很容易利用BeginXxx()方法中的優勢。

使用線程池線程也很便宜,但是您需要遵守線程池調度程序的行爲。這不像啓動更多的TP線程那麼多核心。 TP線程不應該用於代碼,可以保持阻塞一段時間,非常典型的CS任務,如建立連接。

異步代碼中的錯誤處理非常困難。當EndXxxx()方法引發異常時,通常情況下只有很少的上下文。它發生在一個回調線程上,離主邏輯很遠。好吧,當你可以聳聳肩「沒有發生,讓我們記錄下來」,當程序的狀態取決於它時,總體情況和紅色。在後一種情況下總是選擇同步模式。

+1

+1它們甚至比這更好:通常不需要內核線程(大多數驅動程序甚至沒有線程)。 – 2010-07-01 22:30:09

+0

+1 vrey有用的答案。深深的謝謝! – 2010-07-01 22:46:47

0

在您對執手鎖同步服務器當訪問你的數據結構時(如果有更新),這需要時間和代碼(並且是難以發現錯誤的來源)。在許多實現中(例如,用於堆棧分配)也具有許多(例如數千)線程帶來了技術問題,並且如果服務器是IO限制,那些線程幾乎全部正在休眠(等待網絡)並且正在浪費存儲器。在一個線程中使用異步模型,您可以忽略鎖定問題(這意味着您的處理速度儘可能快),並且僅使用客戶端實際需要的內存(只有一個堆棧)。

但是現在多核機器很常見,所以部分優勢就會丟失(因爲如果修改共享數據結構就必須鎖定)。在N個異步服務器前面使用平衡器可能會獲得最佳效率,其中N是您的環境的最佳線程數。

異步方法的壞處在於,根據您的工具,代碼可能非常難看並且難以理解,如果計算不是微不足道的,並且錯誤地處理進入無限循環,則整個異步服務器將無響應(所以應該添加一個看門狗)。

+0

異步並不解決鎖定問題。您可以通過不同線程上的多個回調重新輸入異步回調。使用異步模型時,您仍然需要保護任何共享狀態。 – heavyd 2010-07-01 22:14:27

+0

使用搶先式多線程編碼正確鎖定的問題是切換是「不可見的」,並且可能隨時發生。 異步實現中的切換點是固定的,通常是絕對明顯的。由於確定性,調試也更簡單。 儘管仍然可能存在某種形式的「邏輯」鎖定,但在我看來,與在共享數據更新方法中鎖定權限的困難相比,沒有什麼可比的。 – 6502 2010-07-01 22:35:59

+0

@heavyd:重新閱讀您的評論在我看來,術語存在問題。我說過使用單線程異步實現,你可以忘記鎖定問題......(這意味着關於併發訪問的物理鎖定,而不是自動機的狀態改變之間的邏輯鎖定,當然這是強制的),並且如果異步沒有加上單線程,那麼這個優點就失去了。 在您的評論中,您會討論不同的主題,因此可能會對術語產生誤解。 – 6502 2010-07-02 06:38:00

2

您不想阻止用戶界面。通過異步操作,您可以在等待服務器響應時執行其他操作。

2

異步模式讓您在同步模式讓您等待時繼續處理。

+0

簡單和簡短的答案,但足夠的解釋。 感謝@Brian – 2015-08-12 06:51:05

1

用漢斯的回答「標記」:I/O操作與線程的獨立性允許更顯着的縮放;成千上萬的未完成的請求是可能的,這是無法使用線程完成的。

另外,當你啓動considering the complexities of error handling in protocol design時,事實證明異步方法的複雜程度遠遠低於正確編寫同步代碼的複雜度。大多數同步套接字代碼看起來更簡單,但實際上包含微妙的錯誤。

如果雙方發送的數據比讀取的數據多,則異步方法對於防止死鎖情況也很重要;有關更多討論,請參閱this blog post

如果您希望在線程安全封裝器(具有更簡單的錯誤處理)中實現異步I/O的可靠性優勢和(大部分)性能優勢,請考慮Nito.Async庫。