您好,歡迎進(jìn)入深圳市穎特新科技有限公司官方網(wǎng)站!
1.定義
進(jìn)程是具有一定獨(dú)立功能的程序關(guān)于某個數(shù)據(jù)集合上的一次運(yùn)行活動,進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個獨(dú)立單位.
線程是進(jìn)程的一個實(shí)體,是CPU調(diào)度和分派的基本單位,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位.線程自己基本上不擁有系統(tǒng)資源,只擁有一點(diǎn)在運(yùn)行中必不可少的資源(如程序計(jì)數(shù)器,一組寄存器和棧),但是它可與同屬一個進(jìn)程的其他的線程共享進(jìn)程所擁有的全部資源.
一個線程可以創(chuàng)建和撤銷另一個線程;同一個進(jìn)程中的多個線程之間可以并發(fā)執(zhí)行.
相對進(jìn)程而言,線程是一個更加接近于執(zhí)行體的概念,它可以與同進(jìn)程中的其他線程共享數(shù)據(jù),但擁有自己的?臻g,擁有獨(dú)立的執(zhí)行序列。
進(jìn)程和線程的主要差別在于它們是不同的操作系統(tǒng)資源管理方式。進(jìn)程有獨(dú)立的地址空間,一個進(jìn)程崩潰后,在保護(hù)模式下不會對其它進(jìn)程產(chǎn)生影響,而線程只是一個進(jìn)程中的不同執(zhí)行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨(dú)的地址空間,一個線程死掉就等于整個進(jìn)程死掉,所以多進(jìn)程的程序要比多線程的程序健壯,但在進(jìn)程切換時,耗費(fèi)資源較大,效率要差一些。但對于一些要求同時進(jìn)行并且又要共享某些變量的并發(fā)操作,只能用線程,不能用進(jìn)程。
1) 簡而言之,一個程序至少有一個進(jìn)程,一個進(jìn)程至少有一個線程.
2) 線程的劃分尺度小于進(jìn)程,使得多線程程序的并發(fā)性高。
3) 另外,進(jìn)程在執(zhí)行過程中擁有獨(dú)立的內(nèi)存單元,而多個線程共享內(nèi)存,從而極大地提高了程序的運(yùn)行效率。
4) 線程在執(zhí)行過程中與進(jìn)程還是有區(qū)別的。每個獨(dú)立的線程有一個程序運(yùn)行的入口、順序執(zhí)行序列和程序的出口。但是線程不能夠獨(dú)立執(zhí)行,必須依存在應(yīng)用程序中,由應(yīng)用程序提供多個線程執(zhí)行控制。
5) 從邏輯角度來看,多線程的意義在于一個應(yīng)用程序中,有多個執(zhí)行部分可以同時執(zhí)行。但操作系統(tǒng)并沒有將多個線程看做多個獨(dú)立的應(yīng)用,來實(shí)現(xiàn)進(jìn)程的調(diào)度和管理以及資源分配。這就是進(jìn)程和線程的重要區(qū)別。
線程和進(jìn)程在使用上各有優(yōu)缺點(diǎn):線程執(zhí)行開銷小,但不利于資源的管理和保護(hù);而進(jìn)程正相反。同時,線程適合于在SMP機(jī)器上運(yùn)行,而進(jìn)程則可以跨機(jī)器遷移。
什么是線程?線程與進(jìn)程有什么關(guān)系?這是一個非常抽象的問題,也是一個特別廣的話題,涉及到非常多的知識。我不能確保能把它講得好,也不能確保講的內(nèi)容全部都正確。即使這樣,我也希望盡可能地把它講通俗一點(diǎn),講得明白一點(diǎn),因?yàn)檫@是個一直困擾我很久的,撲朔迷離的知識領(lǐng)域,希望通過我的理解揭開它一層一層神秘的面紗。
線程是什么?要理解這個概念,需要先了解一下操作系統(tǒng)的一些相關(guān)概念。大部分操作系統(tǒng)(如Windows、Linux)的任務(wù)調(diào)度是采用時間片輪轉(zhuǎn)的搶占式調(diào)度方式,也就是說一個任務(wù)執(zhí)行一小段時間后強(qiáng)制暫停去執(zhí)行下一個任務(wù),每個任務(wù)輪流執(zhí)行。任務(wù)執(zhí)行的一小段時間叫做時間片,任務(wù)正在執(zhí)行時的狀態(tài)叫運(yùn)行狀態(tài),任務(wù)執(zhí)行一段時間后強(qiáng)制暫停去執(zhí)行下一個任務(wù),被暫停的任務(wù)就處于就緒狀態(tài)等待下一個屬于它的時間片的到來。這樣每個任務(wù)都能得到執(zhí)行,由于CPU的執(zhí)行效率非常高,時間片非常短,在各個任務(wù)之間快速地切換,給人的感覺就是多個任務(wù)在“同時進(jìn)行”,這也就是我們所說的并發(fā)(別覺得并發(fā)有多高深,它的實(shí)現(xiàn)很復(fù)雜,但它的概念很簡單,就是一句話:多個任務(wù)同時執(zhí)行)。多任務(wù)運(yùn)行過程的示意圖如下:
圖1:操作系統(tǒng)中的任務(wù)調(diào)度
我們都知道計(jì)算機(jī)的核心是CPU,它承擔(dān)了所有的計(jì)算任務(wù);而操作系統(tǒng)是計(jì)算機(jī)的管理者,它負(fù)責(zé)任務(wù)的調(diào)度、資源的分配和管理,統(tǒng)領(lǐng)整個計(jì)算機(jī)硬件;應(yīng)用程序則是具有某種功能的程序,程序是運(yùn)行于操作系統(tǒng)之上的。
進(jìn)程是一個具有一定獨(dú)立功能的程序在一個數(shù)據(jù)集上的一次動態(tài)執(zhí)行的過程,是操作系統(tǒng)進(jìn)行資源分配和調(diào)度的一個獨(dú)立單位,是應(yīng)用程序運(yùn)行的載體。進(jìn)程是一種抽象的概念,從來沒有統(tǒng)一的標(biāo)準(zhǔn)定義。進(jìn)程一般由程序、數(shù)據(jù)集合和進(jìn)程控制塊三部分組成。程序用于描述進(jìn)程要完成的功能,是控制進(jìn)程執(zhí)行的指令集;數(shù)據(jù)集合是程序在執(zhí)行時所需要的數(shù)據(jù)和工作區(qū);程序控制塊(Program Control Block,簡稱PCB),包含進(jìn)程的描述信息和控制信息,是進(jìn)程存在的唯一標(biāo)志。
進(jìn)程具有的特征:
動態(tài)性:進(jìn)程是程序的一次執(zhí)行過程,是臨時的,有生命期的,是動態(tài)產(chǎn)生,動態(tài)消亡的;
并發(fā)性:任何進(jìn)程都可以同其他進(jìn)程一起并發(fā)執(zhí)行;
獨(dú)立性:進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個獨(dú)立單位;
結(jié)構(gòu)性:進(jìn)程由程序、數(shù)據(jù)和進(jìn)程控制塊三部分組成。
在早期的操作系統(tǒng)中并沒有線程的概念,進(jìn)程是能擁有資源和獨(dú)立運(yùn)行的最小單位,也是程序執(zhí)行的最小單位。任務(wù)調(diào)度采用的是時間片輪轉(zhuǎn)的搶占式調(diào)度方式,而進(jìn)程是任務(wù)調(diào)度的最小單位,每個進(jìn)程有各自獨(dú)立的一塊內(nèi)存,使得各個進(jìn)程之間內(nèi)存地址相互隔離。
后來,隨著計(jì)算機(jī)的發(fā)展,對CPU的要求越來越高,進(jìn)程之間的切換開銷較大,已經(jīng)無法滿足越來越復(fù)雜的程序的要求了。于是就發(fā)明了線程,線程是程序執(zhí)行中一個單一的順序控制流程,是程序執(zhí)行流的最小單元,是處理器調(diào)度和分派的基本單位。一個進(jìn)程可以有一個或多個線程,各個線程之間共享程序的內(nèi)存空間(也就是所在進(jìn)程的內(nèi)存空間)。一個標(biāo)準(zhǔn)的線程由線程ID、當(dāng)前指令指針(PC)、寄存器和堆棧組成。而進(jìn)程由內(nèi)存空間(代碼、數(shù)據(jù)、進(jìn)程空間、打開的文件)和一個或多個線程組成。
前面講了進(jìn)程與線程,但可能你還覺得迷糊,感覺他們很類似。的確,進(jìn)程與線程有著千絲萬縷的關(guān)系,下面就讓我們一起來理一理:
1. 線程是程序執(zhí)行的最小單位,而進(jìn)程是操作系統(tǒng)分配資源的最小單位;
2. 一個進(jìn)程由一個或多個線程組成,線程是一個進(jìn)程中代碼的不同執(zhí)行路線;
3. 進(jìn)程之間相互獨(dú)立,但同一進(jìn)程下的各個線程之間共享程序的內(nèi)存空間(包括代碼段、數(shù)據(jù)集、堆等)及一些進(jìn)程級的資源(如打開文件和信號),某進(jìn)程內(nèi)的線程在其它進(jìn)程不可見;
4. 調(diào)度和切換:線程上下文切換比進(jìn)程上下文切換要快得多。
線程與進(jìn)程關(guān)系的示意圖:
圖2:進(jìn)程與線程的資源共享關(guān)系
圖3:單線程與多線程的關(guān)系
總之,線程和進(jìn)程都是一種抽象的概念,線程是一種比進(jìn)程更小的抽象,線程和進(jìn)程都可用于實(shí)現(xiàn)并發(fā)。
在早期的操作系統(tǒng)中并沒有線程的概念,進(jìn)程是能擁有資源和獨(dú)立運(yùn)行的最小單位,也是程序執(zhí)行的最小單位。它相當(dāng)于一個進(jìn)程里只有一個線程,進(jìn)程本身就是線程。所以線程有時被稱為輕量級進(jìn)程(Lightweight Process,LWP)。
圖4:早期的操作系統(tǒng)只有進(jìn)程,沒有線程
后來,隨著計(jì)算機(jī)的發(fā)展,對多個任務(wù)之間上下文切換的效率要求越來越高,就抽象出一個更小的概念——線程,一般一個進(jìn)程會有多個(也可是一個)線程。
圖5:線程的出現(xiàn),使得一個進(jìn)程可以有多個線程
上面提到的時間片輪轉(zhuǎn)的調(diào)度方式說一個任務(wù)執(zhí)行一小段時間后強(qiáng)制暫停去執(zhí)行下一個任務(wù),每個任務(wù)輪流執(zhí)行。很多操作系統(tǒng)的書都說“同一時間點(diǎn)只有一個任務(wù)在執(zhí)行”。那有人可能就要問雙核處理器呢?難道兩個核不是同時運(yùn)行嗎?
其實(shí)“同一時間點(diǎn)只有一個任務(wù)在執(zhí)行”這句話是不準(zhǔn)確的,至少它是不全面的。那多核處理器的情況下,線程是怎樣執(zhí)行呢?這就需要了解內(nèi)核線程。
多核(心)處理器是指在一個處理器上集成多個運(yùn)算核心從而提高計(jì)算能力,也就是有多個真正并行計(jì)算的處理核心,每一個處理核心對應(yīng)一個內(nèi)核線程。內(nèi)核線程(Kernel Thread,KLT)就是直接由操作系統(tǒng)內(nèi)核支持的線程,這種線程由內(nèi)核來完成線程切換,內(nèi)核通過操作調(diào)度器對線程進(jìn)行調(diào)度,并負(fù)責(zé)將線程的任務(wù)映射到各個處理器上。一般一個處理核心對應(yīng)一個內(nèi)核線程,比如單核處理器對應(yīng)一個內(nèi)核線程,雙核處理器對應(yīng)兩個內(nèi)核線程,四核處理器對應(yīng)四個內(nèi)核線程。
現(xiàn)在的電腦一般是雙核四線程、四核八線程,是采用超線程技術(shù)將一個物理處理核心模擬成兩個邏輯處理核心,對應(yīng)兩個內(nèi)核線程,所以在操作系統(tǒng)中看到的CPU數(shù)量是實(shí)際物理CPU數(shù)量的兩倍,如你的電腦是雙核四線程,打開“任務(wù)管理器\性能”可以看到4個CPU的監(jiān)視器,四核八線程可以看到8個CPU的監(jiān)視器。
圖6:雙核四線程在Windows8下查看的結(jié)果
超線程技術(shù)就是利用特殊的硬件指令,把一個物理芯片模擬成兩個邏輯處理核心,讓單個處理器都能使用線程級并行計(jì)算,進(jìn)而兼容多線程操作系統(tǒng)和軟件,減少了CPU的閑置時間,提高的CPU的運(yùn)行效率。這種超線程技術(shù)(如雙核四線程)由處理器硬件的決定,同時也需要操作系統(tǒng)的支持才能在計(jì)算機(jī)中表現(xiàn)出來。
程序一般不會直接去使用內(nèi)核線程,而是去使用內(nèi)核線程的一種高級接口——輕量級進(jìn)程(Lightweight Process,LWP),輕量級進(jìn)程就是我們通常意義上所講的線程(我們在這稱它為用戶線程),由于每個輕量級進(jìn)程都由一個內(nèi)核線程支持,因此只有先支持內(nèi)核線程,才能有輕量級進(jìn)程。用戶線程與內(nèi)核線程的對應(yīng)關(guān)系有三種模型:一對一模型、多對一模型、多對多模型,在這以4個內(nèi)核線程、3個用戶線程為例對三種模型進(jìn)行說明。
對于一對一模型來說,一個用戶線程就唯一地對應(yīng)一個內(nèi)核線程(反過來不一定成立,一個內(nèi)核線程不一定有對應(yīng)的用戶線程)。這樣,如果CPU沒有采用超線程技術(shù)(如四核四線程的計(jì)算機(jī)),一個用戶線程就唯一地映射到一個物理CPU的線程,線程之間的并發(fā)是真正的并發(fā)。一對一模型使用戶線程具有與內(nèi)核線程一樣的優(yōu)點(diǎn),一個線程因某種原因阻塞時其他線程的執(zhí)行不受影響;此處,一對一模型也可以讓多線程程序在多處理器的系統(tǒng)上有更好的表現(xiàn)。
但一對一模型也有兩個缺點(diǎn):1. 許多操作系統(tǒng)限制了內(nèi)核線程的數(shù)量,因此一對一模型會使用戶線程的數(shù)量受到限制;2. 許多操作系統(tǒng)內(nèi)核線程調(diào)度時,上下文切換的開銷較大,導(dǎo)致用戶線程的執(zhí)行效率下降。
圖7:一對一模型
多對一模型將多個用戶線程映射到一個內(nèi)核線程上,線程之間的切換由用戶態(tài)的代碼來進(jìn)行,因此相對一對一模型,多對一模型的線程切換速度要快許多;此外,多對一模型對用戶線程的數(shù)量幾乎無限制。但多對一模型也有兩個缺點(diǎn):1. 如果其中一個用戶線程阻塞,那么其它所有線程都將無法執(zhí)行,因?yàn)榇藭r內(nèi)核線程也隨之阻塞了;2. 在多處理器系統(tǒng)上,處理器數(shù)量的增加對多對一模型的線程性能不會有明顯的增加,因?yàn)樗械挠脩艟程都映射到一個處理器上了。
圖8:多對一模型
多對多模型結(jié)合了一對一模型和多對一模型的優(yōu)點(diǎn),將多個用戶線程映射到多個內(nèi)核線程上。多對多模型的優(yōu)點(diǎn)有:1. 一個用戶線程的阻塞不會導(dǎo)致所有線程的阻塞,因?yàn)榇藭r還有別的內(nèi)核線程被調(diào)度來執(zhí)行;2. 多對多模型對用戶線程的數(shù)量沒有限制;3. 在多處理器的操作系統(tǒng)中,多對多模型的線程也能得到一定的性能提升,但提升的幅度不如一對一模型的高。
在現(xiàn)在流行的操作系統(tǒng)中,大都采用多對多的模型。
圖9:多對多模型
一個應(yīng)用程序可能是多線程的,也可能是多進(jìn)程的,如何查看呢?在Windows下我們只須打開任務(wù)管理器就能查看一個應(yīng)用程序的進(jìn)程和線程數(shù)。按“Ctrl+Alt+Del”或右鍵快捷工具欄打開任務(wù)管理器。
查看進(jìn)程數(shù)和線程數(shù):
圖10:查看線程數(shù)和進(jìn)程數(shù)
在“進(jìn)程”選項(xiàng)卡下,我們可以看到一個應(yīng)用程序包含的線程數(shù)。如果一個應(yīng)用程序有多個進(jìn)程,我們能看到每一個進(jìn)程,如在上圖中,Google的Chrome瀏覽器就有多個進(jìn)程。同時,如果打開了一個應(yīng)用程序的多個實(shí)例也會有多個進(jìn)程,如上圖中我打開了兩個cmd窗口,就有兩個cmd進(jìn)程。如果看不到線程數(shù)這一列,可以再點(diǎn)擊“查看\選擇列”菜單,增加監(jiān)聽的列。
查看CPU和內(nèi)存的使用率:
在性能選項(xiàng)卡中,我們可以查看CPU和內(nèi)存的使用率,根據(jù)CPU使用記錄的監(jiān)視器的個數(shù)還能看出邏輯處理核心的個數(shù),如我的雙核四線程的計(jì)算機(jī)就有四個監(jiān)視器。
圖11:查看CPU和內(nèi)存的使用率
當(dāng)線程的數(shù)量小于處理器的數(shù)量時,線程的并發(fā)是真正的并發(fā),不同的線程運(yùn)行在不同的處理器上。但當(dāng)線程的數(shù)量大于處理器的數(shù)量時,線程的并發(fā)會受到一些阻礙,此時并不是真正的并發(fā),因?yàn)榇藭r至少有一個處理器會運(yùn)行多個線程。
在單個處理器運(yùn)行多個線程時,并發(fā)是一種模擬出來的狀態(tài)。操作系統(tǒng)采用時間片輪轉(zhuǎn)的方式輪流執(zhí)行每一個線程,F(xiàn)在,幾乎所有的現(xiàn)代操作系統(tǒng)采用的都是時間片輪轉(zhuǎn)的搶占式調(diào)度方式,如我們熟悉的Unix、Linux、Windows及macOS等流行的操作系統(tǒng)。
我們知道線程是程序執(zhí)行的最小單位,也是任務(wù)執(zhí)行的最小單位。在早期只有進(jìn)程的操作系統(tǒng)中,進(jìn)程有五種狀態(tài),創(chuàng)建、就緒、運(yùn)行、阻塞(等待)、退出。早期的進(jìn)程相當(dāng)于現(xiàn)在的只有單個線程的進(jìn)程,那么現(xiàn)在的多線程也有五種狀態(tài),現(xiàn)在的多線程的生命周期與早期進(jìn)程的生命周期類似。
圖12:早期進(jìn)程的生命周期
進(jìn)程在運(yùn)行過程有三種狀態(tài):就緒、運(yùn)行、阻塞,創(chuàng)建和退出狀態(tài)描述的是進(jìn)程的創(chuàng)建過程和退出過程。
創(chuàng)建:進(jìn)程正在創(chuàng)建,還不能運(yùn)行。操作系統(tǒng)在創(chuàng)建進(jìn)程時要進(jìn)行的工作包括分配和建立進(jìn)程控制塊表項(xiàng)、建立資源表格并分配資源、加載程序并建立地址空間;
就緒:時間片已用完,此線程被強(qiáng)制暫停,等待下一個屬于它的時間片到來;
運(yùn)行:此線程正在執(zhí)行,正在占用時間片;
阻塞:也叫等待狀態(tài),等待某一事件(如IO或另一個線程)執(zhí)行完;
退出:進(jìn)程已結(jié)束,所以也稱結(jié)束狀態(tài),釋放操作系統(tǒng)分配的資源。
圖13:線程的生命周期
創(chuàng)建:一個新的線程被創(chuàng)建,等待該線程被調(diào)用執(zhí)行;
就緒:時間片已用完,此線程被強(qiáng)制暫停,等待下一個屬于它的時間片到來;
運(yùn)行:此線程正在執(zhí)行,正在占用時間片;
阻塞:也叫等待狀態(tài),等待某一事件(如IO或另一個線程)執(zhí)行完;
退出:一個線程完成任務(wù)或者其他終止條件發(fā)生,該線程終止進(jìn)入退出狀態(tài),退出狀態(tài)釋放該線程所分配的資源。
掃碼關(guān)注我們
傳真:0755-82591176
郵箱:vicky@yingtexin.net
地址:深圳市龍華區(qū)民治街道民治大道973萬眾潤豐創(chuàng)業(yè)園A棟2樓A08