【面試高頻問題】線程、進程、協程
需要先對 IO 的概念有一定的認識: IO在計算機中指Input/Output,也就是輸入和輸出。
並發與並行
並發:在操作系統中,某一時間段,幾個程序在同一個CPU上運行,但在任意一個時間點上,只有一個程序在CPU上運行。當有多個線程時,如果系統只有一個CPU,那麼CPU不可能真正同時進行多個線程,CPU的運行時間會被劃分成若干個時間段,每個時間段分配給各個線程去執行,一個時間段裏某個線程運行時,其他線程處於掛起狀態,這就是並發。並發解決了程序排隊等待的問題,如果一個程序發生阻塞,其他程序仍然可以正常執行。
並行:當操作系統有多個CPU時,一個CPU處理A線程,另一個CPU處理B線程,兩個線程互相不搶佔CPU資源,可以同時進行,這種方式成為並行。區別- 並發只是在宏觀上給人感覺有多個程序在同時運行,但在實際的單CPU系統中,每一時刻只有一個程序在運行,微觀上這些程序是分時交替執行。
- 在多CPU系統中,將這些並發執行的程序分配到不同的CPU上處理,每個CPU用來處理一個程序,這樣多個程序便可以實現同時執行。
知乎上高贊例子:
- 你喫飯喫到一半,電話來了,你一直到喫完了以後纔去接,這就說明你不支持並發也不支持並行。
- 你喫飯喫到一半,電話來了,你停了下來接了電話,接完後繼續喫飯,這說明你支持並發。
- 你喫飯喫到一半,電話來了,你一邊打電話一邊喫飯,這說明你支持並行。
並發的關鍵是你有處理多個任務的能力,不一定要同時。並行的關鍵是你有同時處理多個任務的能力。所以我認為它們最關鍵的點就是:是否是『同時』。
進程
一個進程好比是一個程序,它是 資源分配的最小單位 。同一時刻執行的進程數不會超過核心數。不過如果問單核CPU能否運行多進程?答案又是肯定的。單核CPU也可以運行多進程,只不過不是同時的,而是極快地在進程間來回切換實現的多進程。舉個簡單的例子,就算是十年前的單核CPU的電腦,也可以聊QQ的同時看視頻。 電腦中有許多進程需要處於「同時」開啟的狀態,而利用CPU在進程間的快速切換,可以實現「同時」運行多個程序。而進程切換則意味著需要保留進程切換前的狀態,以備切換回去的時候能夠繼續接著工作。所以進程擁有自己的地址空間,全局變數,文件描述符,各種硬體等等資源。操作系統通過調度CPU去執行進程的記錄、回復、切換等等。線程
如果說進程和進程之間相當於程序與程序之間的關係,那麼線程與線程之間就相當於程序內的任務和任務之間的關係。所以線程是依賴於進程的,也稱為 「微進程」 。它是 程序執行過程中的最小單元 。一個程序內包含了多種任務。打個比方,用播放器看視頻的時候,視頻輸出的畫面和聲音可以認為是兩種任務。當你拖動進度條的時候又觸發了另外一種任務。拖動進度條會導致畫面和聲音都發生變化,如果進程裏沒有線程的話,那麼可能發生的情況就是:拖動進度條->畫面更新->聲音更新。你會明顯感到畫面和聲音和進度條不同步。但是加上了線程之後,線程能夠共享進程的大部分資源,並參與CPU的調度。意味著它能夠在進程間進行切換,實現「並發」,從而反饋到使用上就是拖動進度條的同時,畫面和聲音都同步了。所以我們經常能聽到的一個詞是「多線程」,就是把一個程序分成多個任務去跑,讓任務更快處理。不過線程和線程之間由於某些資源是獨佔的,會導致鎖的問題。例如Python的GIL多線程鎖。
進程與線程的區別
- 進程是CPU資源分配的基本單位,線程是獨立運行和獨立調度的基本單位(CPU上真正運行的是線程)。
- 進程擁有自己的資源空間,一個進程包含若干個線程,線程與CPU資源分配無關,多個線程共享同一進程內的資源。
- 線程的調度與切換比進程快很多。
CPU密集型代碼(各種循環處理、計算等等):使用多進程。IO密集型代碼(文件處理、網路爬蟲等):使用多線程
阻塞與非阻塞
阻塞是指調用線程或者進程被操作系統掛起。非阻塞是指調用線程或者進程不會被操作系統掛起。同步與非同步
同步是阻塞模式,非同步是非阻塞模式。- 同步就是指一個進程在執行某個請求的時候,若該請求需要一段時間才能返回信息,那麼這個進程將會一直等待下去,知道收到返回信息才繼續執行下去;
- 非同步是指進程不需要一直等下去,而是繼續執行下面的操作,不管其他進程的狀態。當有消息返回式系統會通知進程進行處理,這樣可以提高執行的效率。
由調用方盲目主動問詢的方式是同步調用,由被調用方主動通知調用方任務已完成的方式是非同步調用。看下圖