標籤:

為什麼要了解進程與線程的區別,了解二者的區別有什麼意義呢?

了解進程和線程的區別對寫程序有什麼幫助呢?

不了解二者的區別又會帶來哪些問題呢?


————————————————更新7.3———————————————————————

有評論說這個例子里只要event loop就可以了。我舉這個例子的目的是能夠既簡單又通俗的講一下線程的意義,如果又引入event loop的話,整個問題就變得複雜了。這個例子用多線程做肯定沒有問題,但是用event loop好不好,我就不太清楚了,加上我能想到的多線程的例子很多都是伺服器上的,要說起來的話。。。就更複雜了,所以我覺得還是把event loop撇開比較好。而且我覺得event loop本身就是一個線程,加上主程序需要自己運算什麼的話,不就又變成多線程了?如有不對,請指正。

原來的答案只講了線程的意義,完全沒有將進程和線程的區別,和區別的意義。所以我想把這個粗鄙例子修改一下,讓這個答案既生動有趣又能回答所有的問題。

———————————————————————————————————————————

恩,這玩意兒應該說是需求導向的。(我也不知道怎麼解釋,就拿一個例子來說吧,如果有大牛覺得不對的,請指正)

比如說十幾年前,馬化騰在寫QQ,假設他那個時候不懂多進程多線程。然後他就開始寫啦,這玩意兒不簡單嗎,不就是用戶輸入什麼,把信息打包發到另一個用戶,再顯示出來,卧槽,太簡單,2天就能寫完一個字元界面的qq!

然後想當然的寫出如下偽代碼:

while(1):

wait for user input

send user input by UDP/TCP

display incoming messages

end while

這個代碼很簡單,就是不斷地查詢用戶的輸入情況,然後把輸的東西發給對方,然後把對方發過來的信息顯示到屏幕上。

這麼簡單,如果當年有python,QQ一天就能發布了。馬化騰可開心了,然後就開始調試了。他隊友發了一條信息過來,馬化騰就在自己電腦面前等啊。。。等啊。。。等啊。。。。丫,怎麼還么有信息顯示出來啊?豬隊友啊?小學生啊?會不會打字啊?呆逼啊,又要單步調試啊?馬化騰就開始單步調試了,然後他發現自己的程序卡在了wait for user input上一直不動!對,程序一直在等待輸入,如果不輸入的話,是沒有辦法執行後面的任務的!

那怎麼辦?要不默認如果用戶在1秒以內不輸入,就跳過input階段,直接進入後面接收和顯示?那也不行,這樣會有一定的幾率丟失用戶輸入信息,大爺的!!!

這個時候你就會發現,如果能把輸入和顯示這兩個任務分開,變成兩個「程序」,那就太好了。好,那就分成兩個程序吧,一個負責輸入和發送信息,一個負責讀入信息和顯示。卧槽,真是太天才了!說干就干!要不了多長時間,兩個窗口就誕生了,瞬間覺得自己好牛逼啊!

這個時候,所用的實現方式就是我們說的多進程。這樣的方式會產生很多問題,比如:馬哥突然發現多開幾個聊天窗口的話,會把內存給壓榨乾凈。。。。兩個窗口之間交換數據會很麻煩,得走系統層面才能解決。。。。等等等等

這是為什麼呢?蓋因為多進程的程序,每一個進程都有自己的獨立內存空間和資源,相互都是保密的,這就造成了進程之間通信需要通過系統才能完成,無疑會造成資源浪費和時間浪費。

那怎麼辦?就不能讓兩個「程序」共享同一片內存空間,他們自己之間交換數據而不通過系統嗎?

這時,你才需要一個線程的概念,這就是線程的意義。在一個進程當中,任務需要同時「運行」,不能互相干擾,但是有一些變數,內存,信息之類的又要共享,這才需要到線程。


意義為幫助你決定開發軟體時採用多進程架構還是多線程架構。不了解這種區別會在大型軟體的設計開發過程中造成困擾。

Oracle的Unix/Linux版本採用多進程架構,不同的功能模塊由不同的進程負責,Windows版本採用單進程多線程架構,所有的模塊所在線程處在同一個進程當中。

我們來看一下區別:

1.進程管理。Oracle某個模塊掛起了,沒有響應,萬般無奈你要重起這個模塊,Unix平台只要重起這個模塊所在的那個進程就可以了,其它進程保持運行,而Windows平台只有一個進程,只能影響所有模塊,重啟過程中所有模塊都不能提供服務。

2.內存空間。每個進程擁有自己的地址空間,如果只有一個進程,所有模塊共享/約束在同一空間,如果採用多進程,所有進程地址空間獨立,軟體申請/管理更多內存的可能和能力變大了。Unix/Linux環境很多運行在小型機,甚至大型機上,單進程顯然滿足不了需求,Windows運行在PC主機上,對這個沒什麼要求。

3.線程間通信。因為單進程共享地址空間,進程內線程通信效率很高,不同進程的線程之間通信需要某種IPC手段,效率相比降低。其實Linux平台沒有傳統意義的「線程」,所有都是進程,我們看到的進程是一個進程組,裡面的「線程」就是組成這個進程組的進程。

4.資源管理。單進程中其中一個線程操作文件句柄阻塞了,會影響到其它線程對這個句柄的操作,多進程無此問題。一個進程同時打開的句柄是受限制的,多進程意味著可使用更多資源。

5.運行調度。一個線程Hang了就是這個進程Hang了,一個線程Crash了就是這個進程Crash了,所以多線程要格外小心了,多進程分攤風險更安全。

6.軟體開發管理。多進程可以分別交給不同團隊開發,多線程分別交給不同團隊開發很困難,編譯要同步,Debug要同步,進程Crash了是哪個團隊的責任往往要花半天時間。等等。

Oracle的這種思維主要是由資源使用決定的,單進程無法滿足內存,句柄的使用需求時,只能採用多進程。而Windows微內核結構動態創建進程做得不夠好,線程是更好選擇,Linux宏內核結構並且線程本來就是通過進程組的方式實現的。

結論是首先由項目規模決定,這是剛需,再者由運行的系統平台決定,非剛需。


實際中的用途就是你知道了它們的區別,才能在工程項目中選擇一個更合適的。

比如為什麼nginx是多進程模型,memcached是多線程模型。

不知道這點區別,就像去開車,卻不知道剎車和手剎的區別


這是《操作系統》課程的核心內容,你上了這門課就明白了,無需贅言。


進程與線程的區別就是它們的主要特性。你要是不知道,怎麼寫用到進程或者線程的程序?


進程是主線程,cpu時間調度以線程為單位。剩下的題主需要了解兩者內存上的區別。


Linux中線程實際上就是一個進程,一個特殊的進程,特殊在於進程間的資源共享(共享內存空間,不同於進程間通信的數據共享),Linux中使用同一個結構 task_struct 描述進程和線程。Linux Kernel Development 一書中這樣描述線程:A thread is simply a new process that happens to share the same address space as its parent.


可執行文件存儲在磁碟上。

打開可執行文件將可執行文件放入內存,創建了相應的進程

有的進程會有多個線程同時進行實現不同的模塊功能,如文本編輯時你可以一邊輸入一邊進行單詞糾錯。

以上是我自己理解的方式的表達。

還可以參考:

進程

線程


線程共存於應用程序中是現代操作系統中的基本特徵和重要標誌。用過UNIX操作系統的讀者知道進程,在UNIX操作系統中,每個應用程序的執行都在操作系統內核中登記一個進程標誌,操作系統根據分配的標誌對應用程序的執行進行調度和系統資源分配,但進程和線程有什麼區別呢?

進程和線程都是由操作系統所體會的程序運行的基本單元,系統利用該基本單元實現系統對應用的並發性。進程和線程的區別在於:

一個程序至少有一個進程,一個進程至少有一個線程。

線程的劃分尺度小於進程,使得多線程程序的並發性高。

另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。

線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。

從邏輯角度來看,多線程的意義在於一個應用程序中,有多個執行部分可以同時執行。但操作系統並沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。

進程是具有一定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位。進程(Process)是最初定義在 Unix等多用戶、多任務操作系統環境下用於表示應用程序在內存環境中基本執行單元的概念。以Unix操作系統為例,進程是Unix操作系統環境中的基本成分、是系統資源分配的基本單位。Unix操作系統中完成的幾乎所有用戶管理和資源分配等工作都是通過操作系統對應用程序進程的控制來實現的。
線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源。
一個線程可以創建和撤銷另一個線程,同一個進程中的多個線程之間可以並發執行。

進程和線程的主要差別在於它們是不同的操作系統資源管理方式。進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變數,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對於一些要求同時進行並且又要共享某些變數的並發操作,只能用線程,不能用進程。如果有興趣深入的話,我建議你們看看《現代操作系統》或者《操作系統的設計與實現》。對就個問題說得比較清楚。

對開發人員來說,線程之間的數據共享比進程之間的容易得多。在 unix 上,進程間數據共享是通過管道、SOCKET、共享內存、信號燈等機制實現的,在 windows 上也有一套類似的機制。而線程間數據共享只需要共享全局變數即可。多進程無疑比多線程程序更健壯一些,但是代價也是比較大的,特別在進程數或者線程數較多的情況下。

C、C++、Java等語言編寫的源程序經相應的編譯器編譯成可執行文件後,提交給計算機處理器運行。這時處在可執行狀態中的應用程序稱為進程。從用戶角度來看,進程是應用程序的一個執行過程。從操作系統核心角度來看,進程代表的是操作系統分配的內存、CPU時間片等資源的基本單位,是為正在運行的程序提供的運行環境。進程與應用程序的區別在於應用程序作為一個靜態文件存儲在計算機系統的硬碟等存儲空間中,而進程則是處於動態條件下由操作系統維護的系統資源管理實體。多任務環境下應用程序進程的主要特點包括:

●進程在執行過程中有內存單元的初始入口點,並且進程存活過程中始終擁有獨立的內存地址空間;

●進程的生存期狀態包括創建、就緒、運行、阻塞和死亡等類型;

●從應用程序進程在執行過程中向CPU發出的運行指令形式不同,可以將進程的狀態分為用戶態和核心態。處於用戶態下的進程執行的是應用程序指令、處於核心態下的應用程序進程執行的是操作系統指令。

在Unix操作系統啟動過程中,系統自動創建swapper、init等系統進程,用於管理內存資源以及對用戶進程進行調度等。在Unix環境下無論是由操作系統創建的進程還要由應用程序執行創建的進程,均擁有唯一的進程標識(PID)。

參考資料:進程和線程區別


對於軟體工程師來說,操作系統是基礎理論,進程和線程是其中一個核心的概念。

掌握基礎理論的好處是,在你後續編程生涯中,他能幫助你分析問題、解決問題以及寫出更加優雅酷炫性能爆棚的程序。

不僅僅是操作系統,計算機基礎演算法、計算機網路、資料庫等都是。

為什麼要知道這些?因為這是成為優秀工程師必備的基礎能力。


線程是進程中的執行路徑,操作系統為每個進程分配相應的內存空間,而線程是在進程的相應基礎上創建的,線程之間共享進程的資源,如信號,代碼段,數據段和打開的文件描述符,而每個線程只擁有自己的寄存器和局部棧空間


做幾個大一點的RTOS的產品就會逼著自己必須要弄清楚進程和線程的區別了。


從某種意義上講,了解這個真沒啥必要。前提是你的運行環境不是以進程/線程作為基礎模型,這樣的OS有。


推薦閱讀:

安卓系統的通病後台啟動進程過多,待機狀態下就占內存一半,怎麼解決這種問題呢?
如何看待針對 Windows 系統的 "AtomBombing" 內存注入攻擊 ?
在單線程的情況下,NodeJs是如何分發子任務去執行的?
操作系統用戶級線程能夠調用內核嗎?

TAG:計算機 | 進程 |