線程池
一個線程池的工作線程代表應用程序的高效執行異步回調的集合。線程池主要用于減少應用程序線程的數量并提供工作線程的管理。應用程序可以對工作項進行排隊,將工作與可等待的句柄相關聯,根據計時器自動排隊,并與I / O綁定。
線程池架構
以下應用程序可以從使用線程池中受益:
- 高度并行的應用程序,可以異步分派大量小工作項(例如分布式索引搜索或網絡I / O)。
- 一個創建和銷毀大量線程的應用程序,每個線程都運行一小段時間。使用線程池可以降低線程管理的復雜性以及線程創建和銷毀所涉及的開銷。
- 在后臺和并行處理獨立工作項的應用程序(例如加載多個選項卡)。
- 必須對內核對象執行獨占等待或阻止對象上的傳入事件的應用程序。使用線程池可以減少線程管理的復雜性,并通過減少上下文切換的數量來提高性能。
- 一個創建自定義服務器線程以等待事件的應用程序。
原始線程池已在Windows Vista中完全重新架構。新線程池得到改進,因為它提供單個工作線程類型(支持I / O和非I / O),不使用計時器線程,提供單個計時器隊列,并提供專用的持久線程。它還提供清理組,更高的性能,獨立調度的每個進程的多個池以及新的線程池API。
線程池架構包括以下內容:
- 執行回調函數的工作線程
- 等待多個等待句柄的服務員線程
- 工作隊列
- 每個進程的默認線程池
最佳實踐
新的線程池API比原始線程池API提供更多的靈活性和控制。但是,有一些微妙但重要的差異。在原始API中,等待重置是自動的; 在新的API中,每次都必須顯式重置等待。原始API自動處理模擬,將調用進程的安全上下文傳遞給線程。使用新API,應用程序必須顯式設置安全上下文。
以下是使用線程池時的最佳做法:
- 進程的線程共享線程池。單個工作線程可以一次執行多個回調函數。這些工作線程由線程池管理。因此,不要通過在線程上調用TerminateThread或通過從回調函數調用ExitThread來終止線程池中的線程。
- I / O請求可以在線程池中的任何線程上運行。取消線程池線程上的I / O需要同步,因為取消功能可能在與處理I /
O請求的線程不同的線程上運行,這可能導致取消未知操作。為避免這種情況,請始終提供OVERLAPPED結構,在為異步I / O
調用CancelIoEx時啟動I / O請求,或使用您自己的同步確保在調用之前不能在目標線程上啟動其他I /
O.在CancelSynchronousIo或CancelIoEx功能。 - 在從函數返回之前清除在回調函數中創建的所有資源。這些包括TLS,安全上下文,線程優先級和COM注冊。回調函數還必須在返回之前恢復線程狀態。
- 保持等待句柄及其關聯對象保持活動狀態,直到線程池發出信號表示已完成句柄為止。
- 標記正在等待冗長操作的所有線程(例如I / O刷新或資源清理),以便線程池可以分配新線程而不是等待這個線程。
- 在卸載使用線程池的DLL之前,取消所有工作項,I / O,等待操作和計時器,并等待執行回調。
- 通過消除工作項之間和回調之間的依賴關系,確保回調不等待自身完成,以及保留線程優先級,避免死鎖。
- 在使用默認線程池的其他組件的進程中,不要太快地排隊太多項目。每個進程有一個默認線程池,包括Svchost.exe。默認情況下,每個線程池最多包含500個工作線程。當處于就緒/運行狀態的工作線程數必須小于處理器數時,線程池會嘗試創建更多工作線程。
- 避免使用COM單線程單元模型,因為它與線程池不兼容。STA創建線程狀態,可以影響線程的下一個工作項。STA通常是長期存在的并且具有線程親和性,這與線程池相反。
- 創建新的線程池以控制線程優先級和隔離,創建自定義特征,并可能提高響應能力。但是,其他線程池需要更多系統資源(線程,內核內存)。池太多會增加CPU爭用的可能性。
- 如果可能,使用可等待的對象而不是基于APC的機制來發出線程池線程的信號。APC與其他信令機制的線程池線程不兼容,因為系統控制線程池線程的生命周期,因此可以在傳遞通知之前終止線程。
- 使用線程池調試器擴展名!tp。此命令具有以下用法:
- 池地址 標志
- obj 地址 標志
- tqueue
- 地址
- 標志
- 服務員地址
- 工人地址
對于pool,waiter和worker,如果地址為零,則命令將轉儲所有對象。對于服務員和工作人員,省略地址會轉儲當前線程。定義了以下標志:0x1(單行輸出),0x2(轉儲成員)和0x4(轉儲池工作隊列)。
相關話題
線程池API
使用線程池功能