進程是一個具備必定獨立功能的程序關於某次數據集合的一次運行活動,它是操做系統分配資源的基本單元。它能夠申請和擁有系統資源,是一個動態的概念,是一個活動的實體。它不僅是程序的代碼,還包括當前的活動,經過程序計數器的值和處理寄存器的內容來表示。進程的概念主要有兩點:第一,進程是一個實體。每個進程都有它本身的地址空間,通常狀況下,包括文本段、數據段和堆棧段。文本段存儲處理器執行的代碼;數據段儲變量和進程執行期間使用的動態分配的內存;堆棧段存儲着活動過程調用的指令和本地變量。第二,進程是一個「執行中的程序」。程序是一個沒有生命的實體,只有處理器賦予程序生命時(操做系統執行之),它才能成爲一個活動的實體,咱們稱其爲進程。多線程
線程是進程的一個執行流,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。一個標準的線程由線程ID,當前指令指針(PC),寄存器集合和堆棧組 成。另外,線程是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程本身不擁有系統資源,只擁有一點兒在運行中必不可少的資源,每個程序都至少有一個線程,若程序只有一個線程,那就是程序自己。併發
協程是一種編譯器級實現的用戶態的輕量級線程,本質上講只是線程的一種實現。相對於線程,協程也相對獨立,有本身的上下文,可是其切換由程序本身控制。函數
以上是抽象概念,它們的特性也很大程度取決於具體實現(操做系統或者編譯器)。好比LINUX的線程實現就和WINDOWS有很大不一樣,LINUX的線程實際上是輕量級進程(Light Weight Process,LWP),GO的協程也和C#的協程不一樣。性能
若是把進程比做工廠裏的一個車間,車間裏有各類的原材料,設備,和工做人員等等。那麼線程就是車間裏的生產線,它們負責整個車間的生產工做,共享車間內的其它資源,一個車間最少有一個生產線,也能夠有多個。協程就好像是生產線裏更小的生產單位,可以被一些閥門控制。操作系統
從概念上看,協程實際上是線程的一種實現,因此能夠先簡單的認爲協程就是線程的一種。而多進程和多線程程序卻有着比較大的區別。線程
在WINDOWS和LINUX下的進程建立不太同樣。指針
LINUX的fork()是函數經過系統調用建立一個與原來進程幾乎徹底相同的進程,exec()則是用來啓動另外的進程以取代當前運行的進程,一個進程一旦調用exec類函數,它自己就"死亡"了,系統把代碼段替換成新的程序的代碼,廢棄原有的數據段和堆棧段,併爲新程序分配新的數據段與堆棧段,惟一留下的,就是進程號。協程
WINDOWS則是用CreateProccess()來建立一個新的進程,這個新進程運行指定的可執行文件,看上去效果和LINUX的fork()+exec()差很少,只是實現上不太相同。blog
將多個用戶級線程映射到一個內核級線程,線程管理在用戶空間完成,這種模型下操做系統並不知道多線程的存在。如的GO(1.5之前)就是這種模型。
優勢:線程管理是在用戶空間進行的,切換上下文開銷比較小,性能較高。
缺點:當一個線程在使用內核服務時被阻塞,那麼整個進程都會被阻塞;多個線程不能並行地運行在多處理機上。隊列
將每一個用戶級線程映射到一個內核級線程。Java的線程就屬於這種模型。
優勢:當一個線程被阻塞後,容許另外一個線程繼續執行,因此併發能力較強;能很好的利用到CPU的多核心。
缺點:每建立一個用戶級線程都須要建立一個內核級線程與其對應,這樣建立線程的開銷比較大,會影響到應用程序的性能。而且切換線程要進出內核,代價比較大。
將n個用戶級線程映射到m個內核級線程上,要求 m <= n。GO(1.5以後)的協程就屬於這種線程模型。
特色:既克服了多對一模型的併發度不高的缺點,又克服了一對一模型的一個用戶進程佔用太多內核級線程,開銷太大的缺點。又擁有多對一模型和一對一模型各自的優勢。
進程間是徹底獨立的個體,多進程環境中,任何一個進程終止不會影響其餘進程,而多線程環境中任何一個線程執行exit系統調用,則全部線程退出,最多見的是因某個線程異常致使程序的退出。
通訊方式,進程間通訊(IPC:無名管道,有名管道,消息隊列,信號,信號量,共享內存等)較爲複雜,線程間能夠直接讀寫進程數據段(如全局變量)來進行通訊(須要線程同步和互斥手段的輔助,以保證數據的一致性)。
線程比進程輕,不論是建立仍是上下文切換,線程的開銷都要比進程小。