可能從事開發的讀者都聽說過這些專業名詞,但又多少人理解了?
首先,從定義開始,先看一下教科書上?進程和線程定義:
進程:資源分配的最小單位。
線程:程序執行的最小單位。
心中默念,啥啥啥,寫的這是啥。
?
1、進程
進程是程序執行時的一個實例,即它是程序已經執行到課中程度的數據結構的匯集。從內核的觀點看,進程的目的就是擔當分配系統資源(CPU時間、內存等)的基本單位。 舉例說明進程: 想象一位有一手好廚藝的計算機科學家正在為他的女兒烘制生日蛋糕。他有做生日蛋糕的食譜,廚房里有所需的原料:面粉、雞蛋、糖、香草汁等。 在這個比喻中,做蛋糕的食譜就是程序(即用適當形式描述的算法)計算機科學家就是處理器(CPU),而做蛋糕的各種原料就是輸入數據。 進程就是廚師閱讀食譜、取來各種原料以及烘制蛋糕等一系列動作的總和。現在假設計算機科學家的兒子哭著跑了進來,說他的頭被一只蜜蜂蟄了。 計算機科學家就記錄下他照著食譜做到哪兒了(保存進程的當前狀態),然后拿出一本急救手冊,按照其中的指示處理蟄傷。 這里,我們看到處理機制是從一個進程(做蛋糕)切換到另一個高優先級的進程(實施醫療救治),每個進程擁有各自的程序(食譜和急救手冊)。 當蜜蜂蟄傷處理完之后,這位計算機科學家又回來做蛋糕,從他離開時的那一步繼續做下去。
2、線程
線程是CPU調度的最小單位(程序執行流的最小單元),它被包含在進程之中,是進程中的實際運作單元。 一條線程是進程中一個單一順序的控制流,一個進程中可以并發多個線程,每條線程并行執行不同的任務。 一個標準的線程有線程ID、當前指令指針(PC),寄存器集合和堆棧組成。 另外,線程是進程中的一個實體,是被系統獨立調度和分派的基本單元,線程自己不擁有系統資源,只擁有一點兒在運行中必不可少的資源,但它可與同屬一個進程的其他線程共享進程所擁有的全部資源。 一個線程可以創建和撤銷另一個線程,同一進程中的多個線程之間可以并發執行。由于線程之間的相互制約,致使線程在運行中呈現處間斷性。 線程也有就緒、阻塞和運行三種基本狀態。 就緒狀態是指線程具備運行的所有條件,邏輯上可以運行,在等待處理機;運行狀態是指線程占有處理機正在運行;阻塞狀態是指線程在等待一個事件(如某個信號量),邏輯上不可執行。 每一個程序都至少有一個線程,若程序只有一個線程,那就是程序本身。 舉例說明線程: 假設,一個文本程序,需要接受鍵盤輸入,將內容顯示在屏幕上,還需要保存信息到硬盤中。若只有一個進程,勢必造成同一時間只能干一樣事的尷尬(當保存時,就不能通過鍵盤輸入內容)。 若有多個進程,每個進程負責一個任務,進程A負責接收鍵盤輸入的任務,進程B負責將內容顯示在屏幕上的任務,進程C負責保存內容到硬盤中的任務。 這里進程A,B,C間的協作涉及到了進程通信問題,而且有共同都需要擁有的東西——-文本內容,不停的切換造成性能上的損失。 若有一種機制,可以使任務A,B,C共享資源,這樣上下文切換所需要保存和恢復的內容就少了,同時又可以減少通信所帶來的性能損耗,那就好了。這種機制就是線程。 總的來說:進程有獨立的地址空間,線程沒有單獨的地址空間(同一進程內的線程共享進程的地址空間)。 一個進程最多可以創建多少個線程
3、多進程
進程是程序在計算機上的一次執行活動。當你運行一個程序,你就啟動了一個進程。Linux 中的各種棧:進程棧 線程棧 內核棧 中斷棧
顯然,程序是死的(靜態的),進程是活的(動態的)。進程可以分為系統進程和用戶進程。凡是用于完成操作系統的各種功能的進程就是系統進程,它們就是處于運行狀態下的操作系統本身;所有由用戶啟動的進程都是用戶進程。 進程是操作系統進行資源分配的單位。進程又被細化為線程,也就是一個進程下有多個能獨立運行的更小的單位。 在同一個時間里,同一個計算機系統中如果允許兩個或兩個以上的進程處于運行狀態,這便是多任務。現代的操作系統幾乎都是多任務操作系統,能夠同時管理多個進程的運行。 多任務帶來的好處是明顯的,比如你可以邊聽網易云音樂,一邊上網,與此同時甚至可以將下載的文檔打印出來,而這些任務之間絲毫不會相互干擾。 那么這里就涉及到并行的問題,俗話說,一心不能二用,這對計算機也一樣,原則上一個CPU只能分配給一個進程,以便運行這個進程。 我們通常使用的計算機中只有一個CPU,也就是說只有一顆心,要讓它一心多用,同時運行多個進程,就必須使用并發技術。 實現并發技術相當復雜,最容易理解的是“時間片輪轉進程調度算法”,它的思想簡單介紹如下: 在操作系統的管理下,所有正在運行的進程輪流使用CPU,每個進程允許占用CPU的時間非常短(比如10毫秒),這樣用戶根本感覺不出來 CPU是在輪流為多個進程服務,就好像所有的進程都在不間斷地運行一樣。 但實際上在任何一個時間內有且僅有一個進程占有CPU。如果一臺計算機有多個CPU,情況就不同了,如果進程數小于CPU數,則不同的進程可以分配給不同的CPU來運行,這樣,多個進程就是真正同時運行的,這便是并行。 并行處理(Parallel Processing)是計算機系統中能同時執行兩個或更多個處理的一種計算方法。并行處理可同時工作于同一程序的不同方面。 并行處理的主要目的是節省大型和復雜問題的解決時間。 并發處理(concurrency Processing):指一個時間段中有幾個程序都處于已啟動運行到運行完畢之間,且這幾個程序都是在同一個處理機(CPU)上運行,但任一個時刻點上只有一個程序在處理機(CPU)上運行 并發的關鍵是你有處理多個任務的能力,不一定要同時。并行的關鍵是你有同時處理多個任務的能力。所以說,并行是并發的子集。
4、多線程
線程是程序中一個單一的順序控制流程。進程內一個相對獨立的、可調度的執行單元,是系統獨立調度和分派CPU的基本單元。 在單一程序中同時運行多個想成完成不同的工作,稱為多線程。 多線程是為了使得多個線程并行的工作以完成多項任務,以提高系統的效率。線程是在同一時間需要完成多項任務的時候被實現的。 打個比方: 多進程是立體交通系統(近似于立交橋),雖然造價高,上坡下坡多耗點油,但是不堵車。 多線程是平面交通系統,造價低,但紅綠燈太多,老堵車。?
5、線程與進程的關系
(1)一個線程只能屬于一個進程,而一個進程可以有多個線程,但至少有一個線程; (2)資源分配給進程,同一進程內的所有線程共享該進程的所有資源; (3)線程在執行過程中需要協作同步。不同進程中的線程之間要利用消息通信的方法實現同步; (4)處理機分配給線程,即真正在處理機上運行的是線程; (5)線程是進程的一個執行單元,也是進程內的可調用實體。
6、線程與進程的區別
(1)線程共享內存空間;進程的內存是獨立的; (2)同一個進程的線程之間可以直接交流;兩個進程想通信,必須通過一個中間代理來實現; (3)創建新進程很簡單;創建新進程需要對其父進程進行一個克隆; (4)一個線程可以控制和操作同一進程里的其他線程;但是進程只能操作子進程; (5)改變注線程(如優先權),可能會影響其他線程;改變父進程,不影響子進程。 (6)調度:線程作為分配和調度的基本單位,進程作為擁有資源的基本單位 (7)并發性:不進進程之間可以并發執行,同一進程內的線程也可以并發執行 (8)擁有資源:進程是擁有資源的一個獨立單位,線程不擁有系統資源,但是可以訪問隸屬于進程的系統資源 (9)系統開銷:在創建和撤銷進程的時候,系統都要分配和回收資源,導致系統的明顯大于創建和撤銷線程時的開銷。 但進程有獨立的地址空間,進程崩潰后,在保護模式的下不會對其他進程造成影響,而線程只是進程中的不同執行路徑。 線程有自己的堆棧和局部變量,但線程之間沒有獨立的地址空間,一個線程死后就等于整個進程死掉,所以多進程程序要比多線程程序健壯,但是在進程切換的時候消耗的資源較大,效率差。 根本區別就一點:用多進程每個進程有自己的地址空間(address space),線程則共享地址空間。 總結:多線程執行效率高;? 多進程耗資源,安全。嵌入式軟件編程之多線程與多進程
7、進程的優點
7.1 進程的優點
1)順序程序的特點:具有封閉性和可再現性; 2)程序的并發執行和資源共享。多道程序設計出現后,實現了程序的并發執行和資源共享,提高了系統的效率和系統的資源利用率。
7.2 進程的缺點
操作系統調度切換多個線程要比切換調度進程在速度上快的多。 而且進程間內存無法共享,通訊也比較麻煩。線程之間由于共享進程內存空間,所以交換數據非常方便;在創建或撤消進程時,由于系統都要為之分配和回收資源,導致系統的開銷明顯大于創建或撤消線程時的開銷。??
8、線程的優缺點
8.1 線程的優點
1)它是一種非常"節儉"的多任務操作方式。 在Linux系統下,啟動一個新的進程必須分配給它獨立的地址空間,建立眾多的數據表來維護它的代碼 段、堆棧段和數據段,這是一種"昂貴"的多任務工作方式。 而運行于一個進程中的多個線程,它們彼此之間使用相同的地址空間,共享大部分數據,啟動一個線程 所花費的空間遠遠小于啟動一個進程所花費的空間,而且,線程間彼此切換所需的時間也遠遠小于進程間切換所需要的時間。 當然,在具體的系統上,這個數據可能 會有較大的區別; 2)線程間方便的通信機制,由于同一進程下的線程之間共享數據空間,所以一個線程的數據可以直接為其它線程所用,這不僅快捷,而且方便; 3)使多CPU系統更加有效。操作系統會保證當線程數不大于CPU數目時,不同的線程運行于不同的CPU上; 4)改善程序結構。一個既長又復雜的進程可以考慮分為多個線程,成為幾個獨立或半獨立的運行部分,這樣的程序會利于理解和修改。
8.2 線程的缺點
1)調度時, 要保存線程狀態,頻繁調度,需要占用大量的機時; 2)程序設計上容易出錯(線程同步問題)。
9、多線程的優缺點
9.1 多線程的優點
1)無需跨進程邊界;程序邏輯和控制方式簡單; 2)所有線程可以直接共享內存和變量等; 3)線程方式消耗的總資源比進程方式好。
9.2 多線程的缺點
1)每個線程與主程序共用地址空間,受限于2GB地址空間; 2)線程之間的同步和加鎖控制比較麻煩;一個線程的崩潰可能影響到整個程序的穩定性; 3)到達一定的線程數程度后,即使再增加CPU也無法提高性能,例如Windows Server 2003,大約是1500個左右的線程數就快到極限了(線程堆棧設定為1M),如果設定線程堆棧為2M,還達不到1500個線程總數; 4)線程能夠提高的總性能有限,而且線程多了之后,線程本身的調度也是一個麻煩事兒,需要消耗較多的CPU 。
10、多進程的優缺點
10.1 多進程的優點
1)每個進程互相獨立,不影響主程序的穩定性,子進程崩潰沒關系; 2)通過增加CPU,就可以容易擴充性能; 3)可以盡量減少線程加鎖/解鎖的影響,極大提高性能,就算是線程運行的模塊算法效率低也沒關系; 4)每個子進程都有2GB地址空間和相關資源,總體能夠達到的性能上限非常大。
10.2 多進程的缺點
1)邏輯控制復雜,需要和主程序交互; 2)需要跨進程邊界,如果有大數據量傳送,就不太好,適合小數據量傳送、密集運算 多進程調度開銷比較大。 總結:最好是多進程和多線程結合,即根據實際的需要,每個CPU開啟一個子進程,這個子進程開啟多線程可以為若干同類型的數據進行處理。 當然你也可以利用多線程+CPU+輪詢方式來解決問題……方法和手段是多樣的,關鍵是自己看起來實現方便有能夠滿足要求,代價也合適。 按照多個不同的維度(類別),來看看多線程和多進程的對比(注:因為是感性的比較,因此都是相對的,不是說一個好得不得了,另外一個差的無法忍受)。
?
? ? 對比類別 | ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 多進程 | ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?多線程 | ? ? ?總結 |
數據共享、同步 | 數據共享復雜,需要用IPC;數據是分開的,同步簡單 | 因為共享進程數據,數據共享簡單,但也是因為這個原因導致同步復雜 | ?各有優勢 |
? ? 內存、CPU | 占用內存多,切換復雜,CPU利用率低 | 占用內存少,切換簡單,CPU利用率高 | ?線程占優 |
?創建銷毀、切換 | 創建銷毀、切換復雜,速度慢 | 創建銷毀、切換簡單,速度很快 | ?線程占優 |
? ? 編程、調試 | 編程簡單,調試簡單 | 編程復雜,調試復雜 | ?進程占優 |
? ? ? ?可靠性 | 進程間不會互相影響 | 一個線程掛掉將導致整個進程掛掉 | ?進程占優 |
? ? ? ?分布式 | 適應于多核、多機分布式;如果一臺機器不夠,擴展到多臺機器比較簡單 | 適應于多核分布式 | ?進程占優 |
?
其實沒有絕對的好與壞,只有哪個更加合適的問題。我們來看實際應用中究竟如何判斷更加合適。
1)需要頻繁創建銷毀的優先用線程 這種原則最常見的應用就是Web服務器了,來一個連接建立一個線程,斷了就銷毀線程,要是用進程,創建和銷毀的代價是很難承受的
2)需要進行大量計算的優先使用線程 所謂大量計算,當然就是要耗費很多CPU,切換頻繁了,這種情況下線程是最合適的。這種原則最常見的是圖像處理、算法處理。
3)強相關的處理用線程,弱相關的處理用進程 什么叫強相關、弱相關?理論上很難定義,給個簡單的例子就明白了。 一般的Server需要完成如下任務:消息收發、消息處理。“消息收發”和“消息處理”就是弱相關的任務,而“消息處理”里面可能又分為“消息解碼”、“業務處理”,這兩個任務相對來說相關性就要強多了。 因此“消息收發”和“消息處理”可以分進程設計,“消息解碼”、“業務處理”可以分線程設計。當然這種劃分方式不是一成不變的,也可以根據實際情況進行調整。
4)可能要擴展到多機分布的用進程,多核分布的用線程
5)都滿足需求的情況下,用你最熟悉、最拿手的方式 至于“數據共享、同步”、“編程、調試”、“可靠性”這幾個維度的所謂的“復雜、簡單”應該怎么取舍,我只能說:沒有明確的選擇方法。 但我可以告訴你一個選擇原則:如果多進程和多線程都能夠滿足要求,那么選擇你最熟悉、最拿手的那個。 需要提醒的是:雖然我給了這么多的選擇原則,但實際應用中基本上都是“進程+線程”的結合方式,千萬不要真的陷入一種非此即彼的誤區。
11、多任務(多進程)
現代操作系統比如Mac OS X,UNIX,Linux,Windows等,都是支持“多任務”的操作系統。 什么叫“多任務”呢?簡單地說,就是操作系統可以同時運行多個任務。打個比方,你一邊在用瀏覽器上網,一邊在聽MP3,一邊在用Word寫論文,這就是多任務,至少同時有3個任務正在運行。 還有很多任務悄悄地在后臺同時運行著,只是桌面上沒有顯示而已。 現在,多核CPU已經非常普及了,但是,即使過去的單核CPU,也可以執行多任務。由于CPU執行代碼都是順序執行的,那么,單核CPU是怎么執行多任務的呢? 其實操作系統輪流讓各個任務交替執行,任務1執行0.01秒,切換到任務2,任務2執行0.01秒,再切換到任務3,執行0.01秒……這樣反復執行下去。
表面上看,每個任務都是交替執行的,但是,由于CPU的執行速度實在是太快了,我們感覺就像所有任務都在同時執行一樣。 真正的并行執行多任務只能在多核CPU上實現,但是,由于任務數量遠遠多于CPU的核心數量,所以,操作系統也會自動把很多任務輪流調度到每個核心上執行。 對于操作系統來說,一個任務就是一個進程(Process),比如打開一個瀏覽器就是啟動一個瀏覽器進程,打開一個記事本就啟動了一個記事本進程,打開兩個記事本就啟動了兩個記事本進程,打開一個Word就啟動了一個Word進程。 有些進程還不止同時干一件事,比如Word,它可以同時進行打字、拼寫檢查、打印等事情。 在一個進程內部,要同時干多件事,就需要同時運行多個“子任務”,我們把進程內的這些 “子任務” 稱為線程(Thread)。
由于每個進程至少要干一件事,所以,一個進程至少有一個線程。 當然,像Word這種復雜的進程可以有多個線程,多個線程可以同時執行,多線程的執行方式和多進程是一樣的,也是由操作系統在多個線程之間快速切換,讓每個線程都短暫地交替運行,看起來就像同時執行一樣。 當然,真正地同時執行多線程需要多核CPU才可能實現。
審核編輯:黃飛
評論
查看更多