為了規避多進程模型帶來的問題
- 線程被稱作輕量級進程,是進程的子運行單位
令人感到意外的是,linux不支持原生態的線程(thread),window,solaris都支持,linux把線程當進程一樣對待,管理上略有區別,成為 lwp(light weight process)輕量級進程,線程的創建,撤銷依賴glibc相關
庫,各線程庫對資源的耗用各不相同,linux可以切換線程庫,滿足不同需求!
一個進程地址空間內可以開啟多個線程並發或線程並行,一個進程空間,大致可分為指令區(代碼區),存放數據的(堆,棧),靜態區等,堆區中會存放打開的文件
- 多線程比多進程究竟好在哪
解答這個問題,我們不妨設想這樣一個應用場景:有5個請求訪問同一網頁資源,如果是多進程響應(開5個進程,每個進程響應一個請求)且不說內核空間切換進程帶來的資源消耗,即使返回數據,那么同樣的數據也會在進程空間
有5個備份。線程的好處在於,由於進程空間是共享的(打開的文件,傳入的信號,占用的內存資源比進程有所下降),線程1拿到資源后,線程2可以直接讀取數據,並通過網卡交互給互聯網用戶
如果沒有多顆cpu,線程優勢發揮不出來,多核CPU條件下,進程下的線程可以在多個cpu上並行執行,一個進程乃至一個線程可以有多個執行流,可以更好的分配資源。
值得注意的是一個進程不可能通過開啟無數個線程響應所有請求:例如讀,寫操作不能共享,只能切換;cpu一直在運轉,每秒都查詢線程是否就緒 稱之為忙等使用自旋鎖spin lock,切換出線程謂之閑等,線程切換過快會帶來線程抖動
- 多進程多線程組合使用
通過編程,隔離出一個CPU,然后綁定一個進程,在這個進程下開啟多個線程,讓線程在這個CPU下切換
- 一個線程(你沒看錯,是線程)處理多個請求
一個進程響應一個請求和一個線程響應一個請求的場景,其實請求完成的通知機制都可以用select機制,因為前文提到,linux環境下線程和進程並無實質性不同,線程被看做輕量級進程,如下圖所示,每一個進程或線程
(請求)進來后,內核空間都會分配給一個文件描述符用來說明請求的執行情況(完成/未完成),那么內核每次通知時會遍歷文件描述符,標記該文件描述符的狀態,這種通知機制就是select模型
再回到問題本身,如果一個線程A服務多個請求如果出現阻塞的情形,再切換到別的線程B,就意味着A內的其他請求就無法執行,直到阻塞被釋放,然而這樣做並不合理,因為A內的其他請求可能不是I/O阻塞的,這就決定了,
不能切換線程,同時要在請求的上報機制上做出優化。請求一到達就通知內核空間處理的方式謂之同步,請求到達,達到一定數量時統一通知內核空間謂之異步
通知機制上,可以通知所有的文件描述符,無論完成未完成,也可以只通知完成的,可以通知一次,也可以通知多次;這種可以響應多個請求,又讓請求知道自己的請求是否就緒的處理機制就謂之IO多路復用,或者
是I/O復用
在磁盤I/O上要使用AIO也就是異步I/O,不能因為I/O未完成而阻塞I/O;在某一時刻,如果某個請求尚未完成,那么該請求就處於等待狀態。一旦請求完成,要重新建立這個請求的鏈接,並通知該請求結果就緒,
可以來取數據
網路上喚醒I/O------通過內核的I/O多路復用機制,如select模型;無論什么樣的請求,反映在服務器主機上就是一堆套接字文件,一堆文件描述符,一旦就緒,該請求的文件描述符就會被激活;這就有了通知機制,例如:select