前言
大家好,這里是浩道Linux,主要給大家分享Linux、Python、網(wǎng)絡(luò)通信、網(wǎng)絡(luò)安全等相關(guān)的IT知識(shí)平臺(tái)。
今天浩道跟大家分享一篇關(guān)于進(jìn)程與線程之間關(guān)聯(lián)的硬核干貨,看看大神如何通過通俗易懂的圖文,讓大家更加深刻理解進(jìn)程與線程的區(qū)別!
進(jìn)程和線程的概念
先了解一下操作系統(tǒng)的一些相關(guān)概念,大部分操作系統(tǒng)(如Windows、Linux)的任務(wù)調(diào)度是采用時(shí)間片輪轉(zhuǎn)的搶占式調(diào)度方式,也就是說一個(gè)任務(wù)執(zhí)行一小段時(shí)間后強(qiáng)制暫停去執(zhí)行下一個(gè)任務(wù),每個(gè)任務(wù)輪流執(zhí)行。任務(wù)執(zhí)行的一小段時(shí)間叫做時(shí)間片,任務(wù)正在執(zhí)行時(shí)的狀態(tài)叫運(yùn)行狀態(tài),任務(wù)執(zhí)行一段時(shí)間后強(qiáng)制暫停去執(zhí)行下一個(gè)任務(wù),被暫停的任務(wù)就處于就緒狀態(tài)等待下一個(gè)屬于它的時(shí)間片的到來。這樣每個(gè)任務(wù)都能得到執(zhí)行,由于CPU的執(zhí)行效率非常高,時(shí)間片非常短,在各個(gè)任務(wù)之間快速地切換,給人的感覺就是多個(gè)任務(wù)在“同時(shí)進(jìn)行”,這也就是我們所說的并發(fā)(并發(fā)簡單來說多個(gè)任務(wù)同時(shí)執(zhí)行)。
進(jìn)程
計(jì)算機(jī)的核心是CPU,它承擔(dān)了所有的計(jì)算任務(wù);而操作系統(tǒng)是計(jì)算機(jī)的管理者,它負(fù)責(zé)任務(wù)的調(diào)度、資源的分配和管理,統(tǒng)領(lǐng)整個(gè)計(jì)算機(jī)硬件;應(yīng)用程序側(cè)是具有某種功能的程序,程序是運(yùn)行于操作系統(tǒng)之上的。
進(jìn)程是一個(gè)具有一定獨(dú)立功能的程序在一個(gè)數(shù)據(jù)集上的一次動(dòng)態(tài)執(zhí)行的過程,是操作系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(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í)所需要的數(shù)據(jù)和工作區(qū);程序控制塊(Program Control Block,簡稱PCB),包含進(jìn)程的描述信息和控制信息,是進(jìn)程存在的唯一標(biāo)志。
進(jìn)程具有的特征:
?動(dòng)態(tài)性:進(jìn)程是程序的一次執(zhí)行過程,是臨時(shí)的,有生命期的,是動(dòng)態(tài)產(chǎn)生,動(dòng)態(tài)消亡的;?并發(fā)性:任何進(jìn)程都可以同其他進(jìn)程一起并發(fā)執(zhí)行;?獨(dú)立性:進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位;?結(jié)構(gòu)性:進(jìn)程由程序、數(shù)據(jù)和進(jìn)程控制塊三部分組成。
進(jìn)程的生命周期
在早期只有進(jìn)程的操作系統(tǒng)中,進(jìn)程有五種狀態(tài),創(chuàng)建、就緒、運(yùn)行、阻塞(等待)、退出。
?創(chuàng)建:進(jìn)程正在創(chuàng)建,還不能運(yùn)行。操作系統(tǒng)在創(chuàng)建進(jìn)程時(shí)要進(jìn)行的工作包括分配和建立進(jìn)程控制塊表項(xiàng)、建立資源表格并分配資源、加載程序并建立地址空間;?就緒:時(shí)間片已用完,此線程被強(qiáng)制暫停,等待下一個(gè)屬于他的時(shí)間片到來;?運(yùn)行:此線程正在執(zhí)行,正在占用時(shí)間片;?阻塞:也叫等待狀態(tài),等待某一事件(如IO或另一個(gè)線程)執(zhí)行完;?退出:進(jìn)程已結(jié)束,所以也稱結(jié)束狀態(tài),釋放操作系統(tǒng)分配的資源。
線程
在早期的操作系統(tǒng)中并沒有線程的概念,進(jìn)程是能擁有資源和獨(dú)立運(yùn)行的最小單位,也是程序執(zhí)行的最小單位。任務(wù)調(diào)度采用的是時(shí)間片輪轉(zhuǎn)的搶占式調(diào)度方式,而進(jìn)程是任務(wù)調(diào)度的最小單位,每個(gè)進(jìn)程有各自獨(dú)立的一塊內(nèi)存,使得各個(gè)進(jìn)程之間內(nèi)存地址相互隔離。
后來,隨著計(jì)算機(jī)的發(fā)展,對(duì)CPU的要求越來越高,進(jìn)程之間的切換開銷較大,已經(jīng)無法滿足越來越復(fù)雜的程序的要求了。于是就發(fā)明了線程,線程是程序執(zhí)行中一個(gè)單一的順序控制流程,是程序執(zhí)行流的最小單元,是處理器調(diào)度和分派的基本單位。一個(gè)進(jìn)程可以有一個(gè)或多個(gè)線程,各個(gè)線程之間共享程序的內(nèi)存空間。
一個(gè)標(biāo)準(zhǔn)的線程由線程ID、當(dāng)前指令指針(PC)、寄存器和堆棧組成。而進(jìn)程由內(nèi)存空間(代碼、數(shù)據(jù)、進(jìn)程空間、打開的文件)和一個(gè)或多個(gè)線程組成。
線程的生命周期
當(dāng)線程的數(shù)量小于處理器的數(shù)量時(shí),線程的并發(fā)是真正的并發(fā),不同的線程運(yùn)行在不同的處理器上。但當(dāng)線程的數(shù)量大于處理器的數(shù)量時(shí),線程的并發(fā)會(huì)受到一些阻礙,此時(shí)并不是真正的并發(fā),因?yàn)榇藭r(shí)至少有一個(gè)處理器會(huì)運(yùn)行多個(gè)線程。在單個(gè)處理器運(yùn)行多個(gè)線程時(shí),并發(fā)是一種模擬出來的狀態(tài)。操作系統(tǒng)采用時(shí)間片輪轉(zhuǎn)的方式輪流執(zhí)行每一個(gè)線程。現(xiàn)在,幾乎所有的現(xiàn)代操作系統(tǒng)采用的都是時(shí)間片輪轉(zhuǎn)的搶占式調(diào)度方式,如我們熟悉的Unix、linux、Windows及Mac OS X等流行的操作系統(tǒng)。
?創(chuàng)建:一個(gè)新的線程被創(chuàng)建,等待該線程被調(diào)用執(zhí)行;?就緒:時(shí)間片已用完,此線程被強(qiáng)制暫停,等待下一個(gè)屬于他的時(shí)間片到來;?運(yùn)行:此線程正在執(zhí)行,正在占用時(shí)間片;?阻塞:也叫等待狀態(tài),等待某一事件(如IO或另一個(gè)線程)執(zhí)行完;?退出:一個(gè)線程完成任務(wù)或者其他終止條件發(fā)生,該線程終止進(jìn)入退出狀態(tài),退出狀態(tài)釋放該線程所分配的資源。
線程優(yōu)先級(jí)
操作系統(tǒng)(如Windows、Linux、Mac OS X)的任務(wù)調(diào)度除了具有前面提到的時(shí)間片輪轉(zhuǎn)的特點(diǎn)外,還有優(yōu)先級(jí)調(diào)度(Priority Schedule)的特點(diǎn)。優(yōu)先級(jí)調(diào)度決定了線程按照什么順序輪流執(zhí)行,在具有優(yōu)先級(jí)調(diào)度的系統(tǒng)中,線程擁有各自的線程優(yōu)先級(jí)(Thread Priority)。具有高優(yōu)先級(jí)的線程會(huì)更早地執(zhí)行,而低優(yōu)先級(jí)的線程通常要等沒有更高優(yōu)先級(jí)的可執(zhí)行線程時(shí)才會(huì)被執(zhí)行。
線程的優(yōu)先級(jí)可以由用戶手動(dòng)設(shè)置,此外系統(tǒng)也會(huì)根據(jù)不同情形調(diào)整優(yōu)先級(jí)。通常情況下,頻繁地進(jìn)入等待狀態(tài)(進(jìn)入等待狀態(tài)會(huì)放棄之前仍可占用的時(shí)間份額)的線程(如IO線程),比頻繁進(jìn)行大量計(jì)算以至于每次都把所有時(shí)間片全部用盡的線程更受操作系統(tǒng)的歡迎。因?yàn)轭l繁進(jìn)入等待的線程只會(huì)占用很少的時(shí)間,這樣操作系統(tǒng)可以處理更多的任務(wù)。我們把頻繁等待的線程稱之為IO密集型線程(IO Bound Thread),而把很少等待的線程稱之為CPU密集型線程(CPU Bound Thread)。IO密集型線程總是比CPU密集型線程更容易得到優(yōu)先級(jí)的提升。
線程餓死在優(yōu)先級(jí)調(diào)度下,容易出現(xiàn)一種線程餓死的現(xiàn)象。一個(gè)線程餓死是說它的優(yōu)先級(jí)較低,在它執(zhí)行之前總是有比它優(yōu)先級(jí)更高的線程等待執(zhí)行,因此這個(gè)低優(yōu)先級(jí)的線程始終得不到執(zhí)行。當(dāng)CPU密集型的線程優(yōu)先級(jí)較高時(shí),其它低優(yōu)先級(jí)的線程就很可能出現(xiàn)餓死的情況;當(dāng)IO密集型線程優(yōu)先級(jí)較高時(shí),其它線程相對(duì)不容易造成餓死的,因?yàn)镮O線程有大量的等待時(shí)間。為了避免線程餓死,調(diào)度系統(tǒng)通常會(huì)逐步提升那些等待了很久而得不到執(zhí)行的線程的優(yōu)先級(jí)。這樣,一個(gè)線程只要它等待了足夠長的時(shí)間,其優(yōu)先級(jí)總會(huì)被提升到可以讓它執(zhí)行的程度,也就是說這種情況下線程始終會(huì)得到執(zhí)行,只是時(shí)間的問題。
在優(yōu)先級(jí)調(diào)度環(huán)境下,線程優(yōu)先級(jí)的改變有三種方式:
1.用戶指定優(yōu)先級(jí);2.根據(jù)進(jìn)入等待狀態(tài)的頻繁程度提升或降低優(yōu)先級(jí)(由操作系統(tǒng)完成);3.長時(shí)間得不到執(zhí)行而被提升優(yōu)先級(jí)。
多線程與多核上面提到的時(shí)間片輪轉(zhuǎn)的調(diào)度方式說一個(gè)任務(wù)執(zhí)行一小段時(shí)間后強(qiáng)制暫停去執(zhí)行下一個(gè)任務(wù),每個(gè)任務(wù)輪流執(zhí)行。很多操作系統(tǒng)的書都說“同一時(shí)間點(diǎn)只有一個(gè)任務(wù)在執(zhí)行”。其實(shí)“同一時(shí)間點(diǎn)只有一個(gè)任務(wù)在執(zhí)行”這句話是不準(zhǔn)確的,至少它是不全面的。我們分析一下多核的情況。
這是我的電腦的CPU情況圖:
多核(心)處理器是指在一個(gè)處理器上集成多個(gè)運(yùn)算核心從而提高計(jì)算能力,也就是有多個(gè)真正并行計(jì)算的處理核心,每一個(gè)處理核心對(duì)應(yīng)一個(gè)內(nèi)核線程。內(nèi)核線程(Kernel Thread, KLT)就是直接由操作系統(tǒng)內(nèi)核支持的線程,這種線程由內(nèi)核來完成線程切換,內(nèi)核通過操作調(diào)度器對(duì)線程進(jìn)行調(diào)度,并負(fù)責(zé)將線程的任務(wù)映射到各個(gè)處理器上。一般一個(gè)處理核心對(duì)應(yīng)一個(gè)內(nèi)核線程,比如單核處理器對(duì)應(yīng)一個(gè)內(nèi)核線程,雙核處理器對(duì)應(yīng)兩個(gè)內(nèi)核線程,四核處理器對(duì)應(yīng)四個(gè)內(nèi)核線程。
現(xiàn)在的電腦一般是雙核四線程、四核八線程,是采用超線程技術(shù)將一個(gè)物理處理核心模擬成兩個(gè)邏輯處理核心,對(duì)應(yīng)兩個(gè)內(nèi)核線程,所以在操作系統(tǒng)中看到的CPU數(shù)量是實(shí)際物理CPU數(shù)量的兩倍。但是我的如上圖是四核四線程,似乎沒有用這個(gè)超線程技術(shù)。
超線程技術(shù)就是利用特殊的硬件指令,把一個(gè)物理芯片模擬成兩個(gè)邏輯處理核心,讓單個(gè)處理器都能使用線程級(jí)并行計(jì)算,進(jìn)而兼容多線程操作系統(tǒng)和軟件,減少了CPU的閑置時(shí)間,提高的CPU的運(yùn)行效率。這種超線程技術(shù)(如雙核四線程)由處理器硬件的決定,同時(shí)也需要操作系統(tǒng)的支持才能在計(jì)算機(jī)中表現(xiàn)出來。
程序一般不會(huì)直接去使用內(nèi)核線程,而是去使用內(nèi)核線程的一種高級(jí)接口——輕量級(jí)進(jìn)程(Light Weight Process,LWP),輕量級(jí)進(jìn)程就是我們通常意義上所講的線程(我們?cè)谶@稱它為用戶線程),由于每個(gè)輕量級(jí)進(jìn)程都由一個(gè)內(nèi)核線程支持,因此只有先支持內(nèi)核線程,才能有輕量級(jí)進(jìn)程。用戶線程與內(nèi)核線程的對(duì)應(yīng)關(guān)系有三種模型:一對(duì)一模型、多對(duì)一模型、多對(duì)多模型,在這以4個(gè)內(nèi)核線程、3個(gè)用戶線程為例對(duì)三種模型進(jìn)行說明。
一對(duì)一模型對(duì)于一對(duì)一模型來說,一個(gè)用戶線程就唯一地對(duì)應(yīng)一個(gè)內(nèi)核線程(反過來不一定成立,一個(gè)內(nèi)核線程不一定有對(duì)應(yīng)的用戶線程)。這樣,如果CPU沒有采用超線程技術(shù)(如四核四線程的計(jì)算機(jī),就如上圖展示的我使用的計(jì)算機(jī)),一個(gè)用戶線程就唯一地映射到一個(gè)物理CPU的線程,線程之間的并發(fā)是真正的并發(fā)。一對(duì)一模型使用戶線程具有與內(nèi)核線程一樣的優(yōu)點(diǎn),一個(gè)線程因某種原因阻塞時(shí)其他線程的執(zhí)行不受影響;此處,一對(duì)一模型也可以讓多線程程序在多處理器的系統(tǒng)上有更好的表現(xiàn)。但一對(duì)一模型也有兩個(gè)缺點(diǎn):
1.許多操作系統(tǒng)限制了內(nèi)核線程的數(shù)量,因此一對(duì)一模型會(huì)使用戶線程的數(shù)量受到限制;2.許多操作系統(tǒng)內(nèi)核線程調(diào)度時(shí),上下文切換的開銷較大,導(dǎo)致用戶線程的執(zhí)行效率下降。
多對(duì)一模型
多對(duì)一模型將多個(gè)用戶線程映射到一個(gè)內(nèi)核線程上,線程之間的切換由用戶態(tài)的代碼來進(jìn)行,因此相對(duì)一對(duì)一模型,多對(duì)一模型的線程切換速度要快許多;此外,多對(duì)一模型對(duì)用戶線程的數(shù)量幾乎無限制。但多對(duì)一模型也有兩個(gè)缺點(diǎn):
1.如果其中一個(gè)用戶線程阻塞,那么其它所有線程都將無法執(zhí)行,因?yàn)榇藭r(shí)內(nèi)核線程也隨之阻塞了;2.在多處理器系統(tǒng)上,處理器數(shù)量的增加對(duì)多對(duì)一模型的線程性能不會(huì)有明顯的增加,因?yàn)樗械挠脩艟€程都映射到一個(gè)處理器上了。
多對(duì)多模型多對(duì)多模型結(jié)合了一對(duì)一模型和多對(duì)一模型的優(yōu)點(diǎn),將多個(gè)用戶線程映射到多個(gè)內(nèi)核線程上。多對(duì)多模型的優(yōu)點(diǎn)有:
1.一個(gè)用戶線程的阻塞不會(huì)導(dǎo)致所有線程的阻塞,因?yàn)榇藭r(shí)還有別的內(nèi)核線程被調(diào)度來執(zhí)行;2.多對(duì)多模型對(duì)用戶線程的數(shù)量沒有限制;3.在多處理器的操作系統(tǒng)中,多對(duì)多模型的線程也能得到一定的性能提升,但提升的幅度不如一對(duì)一模型的高。
進(jìn)程與線程的區(qū)別
線程是程序執(zhí)行的最小單位,而進(jìn)程是操作系統(tǒng)分配資源的最小單位;
一個(gè)進(jìn)程由一個(gè)或多個(gè)線程組成,線程是一個(gè)進(jìn)程中代碼的不同執(zhí)行路線;
進(jìn)程之間相互獨(dú)立,但同一進(jìn)程下的各個(gè)線程之間共享程序的內(nèi)存空間(包括代碼段、數(shù)據(jù)集、堆等)及一些進(jìn)程級(jí)的資源(如打開文件和信號(hào)),某進(jìn)程內(nèi)的線程在其它進(jìn)程不可見;
調(diào)度和切換:線程上下文切換比進(jìn)程上下文切換要快得多。
總之,線程和進(jìn)程都是一種抽象的概念,線程是一種比進(jìn)程更小的抽象,線程和進(jìn)程都可用于實(shí)現(xiàn)并發(fā)。
在早期的操作系統(tǒng)中并沒有線程的概念,進(jìn)程是能擁有資源和獨(dú)立運(yùn)行的最小單位,也是程序執(zhí)行的最小單位。它相當(dāng)于一個(gè)進(jìn)程里只有一個(gè)線程,進(jìn)程本身就是線程。所以線程有時(shí)被稱為輕量級(jí)進(jìn)程(Lightweight Process,LWP)。
后來,隨著計(jì)算機(jī)的發(fā)展,對(duì)多個(gè)任務(wù)之間上下文切換的效率要求越來越高,就抽象出一個(gè)更小的概念——線程,一般一個(gè)進(jìn)程會(huì)有多個(gè)(也可是一個(gè))線程。
漫話進(jìn)程和線程
1.計(jì)算機(jī)的核心是CPU,它承擔(dān)了所有的計(jì)算任務(wù)。它就像一座工廠,時(shí)刻在運(yùn)行。
2.假定工廠的電力有限,一次只能供給一個(gè)車間使用。也就是說,一個(gè)車間開工的時(shí)候,其他車間都必須停工。背后的含義就是,單個(gè)CPU一次只能運(yùn)行一個(gè)任務(wù)。
3.進(jìn)程就好比工廠的車間,它代表CPU所能處理的單個(gè)任務(wù)。任一時(shí)刻,CPU總是運(yùn)行一個(gè)進(jìn)程,其他進(jìn)程處于非運(yùn)行狀態(tài)。
4.一個(gè)車間里,可以有很多工人。他們協(xié)同完成一個(gè)任務(wù)。
5.線程就好比車間里的工人。一個(gè)進(jìn)程可以包括多個(gè)線程。
6.車間的空間是工人們共享的,比如許多房間是每個(gè)工人都可以進(jìn)出的。這象征一個(gè)進(jìn)程的內(nèi)存空間是共享的,每個(gè)線程都可以使用這些共享內(nèi)存。
7.可是,每間房間的大小不同,有些房間最多只能容納一個(gè)人,比如廁所。里面有人的時(shí)候,其他人就不能進(jìn)去了。這代表一個(gè)線程使用某些共享內(nèi)存時(shí),其他線程必須等它結(jié)束,才能使用這一塊內(nèi)存。
8.一個(gè)防止他人進(jìn)入的簡單方法,就是門口加一把鎖。先到的人鎖上門,后到的人看到上鎖,就在門口排隊(duì),等鎖打開再進(jìn)去。這就叫”互斥鎖”(Mutual exclusion,縮寫 Mutex),防止多個(gè)線程同時(shí)讀寫某一塊內(nèi)存區(qū)域。
9.還有些房間,可以同時(shí)容納n個(gè)人,比如廚房。也就是說,如果人數(shù)大于n,多出來的人只能在外面等著。這好比某些內(nèi)存區(qū)域,只能供給固定數(shù)目的線程使用。
10.這時(shí)的解決方法,就是在門口掛n把鑰匙。進(jìn)去的人就取一把鑰匙,出來時(shí)再把鑰匙掛回原處。后到的人發(fā)現(xiàn)鑰匙架空了,就知道必須在門口排隊(duì)等著了。這種做法叫做”信號(hào)量”(Semaphore),用來保證多個(gè)線程不會(huì)互相沖突。
不難看出,mutex是semaphore的一種特殊情況(n=1時(shí))。也就是說,完全可以用后者替代前者。但是,因?yàn)閙utex較為簡單,且效率高,所以在必須保證資源獨(dú)占的情況下,還是采用這種設(shè)計(jì)。
操作系統(tǒng)的設(shè)計(jì),因此可以歸結(jié)為三點(diǎn):
(1)以多進(jìn)程形式,允許多個(gè)任務(wù)同時(shí)運(yùn)行;
(2)以多線程形式,允許單個(gè)任務(wù)分成不同的部分運(yùn)行;
(3)提供協(xié)調(diào)機(jī)制,一方面防止進(jìn)程之間和線程之間產(chǎn)生沖突,另一方面允許進(jìn)程之間和線程之間共享資源。
審核編輯:湯梓紅
-
Linux
+關(guān)注
關(guān)注
87文章
11304瀏覽量
209536 -
操作系統(tǒng)
+關(guān)注
關(guān)注
37文章
6827瀏覽量
123335 -
python
+關(guān)注
關(guān)注
56文章
4797瀏覽量
84694 -
線程
+關(guān)注
關(guān)注
0文章
504瀏覽量
19687 -
進(jìn)程
+關(guān)注
關(guān)注
0文章
203瀏覽量
13962
原文標(biāo)題:太強(qiáng)了!總算有大神把進(jìn)程與線程之間的關(guān)系講得透徹了~
文章出處:【微信號(hào):浩道linux,微信公眾號(hào):浩道linux】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論