我有一個關于多插座的問題。我知道我必須select()用于多插座。select()等待一個fd......但是select()當我們可以為每個套接字創建一個執行緒并分別accept()在每個套接字上執行時,為什么我們需要使用?這是一個壞主意嗎?是“套接字太多,執行緒太多”還是什么??
uj5u.com熱心網友回復:
確實,您可以通過為每個套接字生成一個執行緒,然后在每個執行緒上使用阻塞 I/O 來避免多路復用套接字。
這使您不必處理select()(poll()或等);但現在你必須處理多個執行緒,這通常更糟。
在您的特定程式中,執行緒是否比套接字多路復用更麻煩管理在很大程度上取決于您的程式正在嘗試做什么。例如,如果程式中的執行緒不需要相互通信/合作或共享任何資源,那么多執行緒設計可以很好地作業(就像多行程設計一樣)。另一方面,如果您的執行緒都需要訪問共享資料結構或其他資源,或者如果它們需要相互互動,那么您將面臨一些編程挑戰,您需要這樣做要 100% 完美解決,否則您最終會得到一個“似乎大部分時間都在作業”的程式,但有時會由于不正確/不充分的同步而導致死鎖、崩潰或給出不正確的結果。這種“亞穩”現象
除了穩定性和代碼正確性問題之外,使用單執行緒設計還可以避免一些多執行緒特有的其他問題:
大多數作業系統不能很好地擴展到幾十個執行緒以上。因此,如果您考慮每個客戶端一個執行緒,并且您想要支持成百上千個并發客戶端,那么您會遇到一些性能問題。
很難控制在阻塞套接字呼叫中被阻塞的執行緒。假設用戶按下了 Command-Q(或任何適當的等效鍵),那么現在是退出程式的時候了。如果在阻塞套接字呼叫中阻塞了一個或多個執行緒,則沒有直接的方法可以做到這一點:
- 你不能單方面呼叫exit(),因為當主執行緒正在拆除行程全域資源時,一個或多個執行緒可能仍在使用它們,導致偶爾的崩潰
- 您不能要求執行緒退出(通過 atomic-boolean 或其他方式)然后呼叫
join()等待它們,因為它們在 I/O 呼叫中阻塞,因此可能需要幾分鐘/幾小時/幾天才能做出回應 - 您無法向執行緒發送信號并讓它們在信號處理程式中做出反應,因為信號是每個行程的,并且您無法控制哪個執行緒將接收信號。
- 您不能單方面終止執行緒,因為它們可能持有資源(如互斥體或檔案句柄),然后將永遠保持未釋放狀態,從而可能導致死鎖或其他問題
- 您不能為它們關閉執行緒的套接字,并希望這會導致執行緒出錯并終止,因為如果執行緒也嘗試關閉這些相同的資源,這會導致競爭條件。
- 因此,即使在多執行緒設計中,如果您想要完全關閉(或任何其他型別的網路執行緒本地控制),您通常最終必須在每個執行緒內使用非阻塞 I/O 和/或套接字多路復用,所以現在你有兩個世界中最糟糕的,復雜性。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/345041.html
上一篇:套接字的真正定義是什么?
