<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一文快速了解進(jìn)程、線程與協(xié)程

          共 5533字,需瀏覽 12分鐘

           ·

          2021-06-17 13:02

          進(jìn)程與線程

          進(jìn)程是操作系統(tǒng)進(jìn)行資源分配的基本單位,每個進(jìn)程都有自己的獨立內(nèi)存空間。由于進(jìn)程比較重量,占據(jù)獨立的內(nèi)存,所以上下文進(jìn)程間的切換開銷(棧、寄存器、虛擬內(nèi)存、文件句柄等)比較大,但相對比較穩(wěn)定安全。

          線程又叫做輕量級進(jìn)程,是進(jìn)程的一個實體,是處理器任務(wù)調(diào)度和執(zhí)行的基本單位位。它是比進(jìn)程更小的能獨立運行的基本單位。線程只擁有一點在運行中必不可少的資源(如程序計數(shù)器,一組寄存器和棧),但是它可與同屬一個進(jìn)程的其他的線程共享進(jìn)程所擁有的全部資源。

          對于操作系統(tǒng)來說,一個任務(wù)就是一個進(jìn)程(Process)。比如打開一個瀏覽器就是啟動一個瀏覽器進(jìn)程,打開一個記事本就啟動了一個記事本進(jìn)程,打開兩個記事本就啟動了兩個記事本進(jìn)程,打開一個Word就啟動了一個Word進(jìn)程。

          有些進(jìn)程還不止同時干一件事,比如Word,它可以同時進(jìn)行打字、拼寫檢查、打印等事情。在一個進(jìn)程內(nèi)部,要同時干多件事,就需要同時運行多個“子任務(wù)”,進(jìn)程內(nèi)的這些“子任務(wù)”稱為線程(Thread)。

          由于每個進(jìn)程至少要干一件事,所以,一個進(jìn)程至少有一個線程。當(dāng)然,像Word這種復(fù)雜的進(jìn)程可以有多個線程,多個線程可以同時執(zhí)行,多線程的執(zhí)行方式和多進(jìn)程是一樣的,也是由操作系統(tǒng)在多個線程之間快速切換,讓每個線程都短暫地交替運行,看起來就像同時執(zhí)行一樣。

          協(xié)程

          協(xié)程,又稱微線程,是一種用戶態(tài)的輕量級線程,協(xié)程的調(diào)度完全由用戶控制(也就是在用戶態(tài)執(zhí)行)。協(xié)程擁有自己的寄存器上下文和棧。協(xié)程調(diào)度切換時,將寄存器上下文和棧保存到線程的堆區(qū),在切回來的時候,恢復(fù)先前保存的寄存器上下文和棧,直接操作棧則基本沒有內(nèi)核切換的開銷,可以不加鎖的訪問全局變量,所以上下文的切換非常快。

          如果對內(nèi)核態(tài)用戶態(tài)不了解的話,可以先看博客《一文理解JVM線程屬于用戶態(tài)還是內(nèi)核態(tài)

          協(xié)程最大的優(yōu)勢就是協(xié)程極高的執(zhí)行效率。因為子程序切換不是線程切換,而是由程序自身控制,因此,沒有線程切換的開銷,和線程切換相比,線程數(shù)量越多,協(xié)程的性能優(yōu)勢就越明顯。不需要多線程的鎖機(jī)制,因為只有一個線程,也不存在同時寫變量沖突,在協(xié)程中控制共享資源不加鎖,只需要判斷狀態(tài)就好了,所以執(zhí)行效率比多線程高很多。此外,一個線程的內(nèi)存在MB級別,而協(xié)程只需要KB級別。

          進(jìn)程和線程的區(qū)別

          每個線程都是一個輕量級進(jìn)程(Light Weight Process),都有自己的唯一PID和一個TGID(Thread group ID)。TGID是啟動整個進(jìn)程的thread的PID。

          例如,當(dāng)一個進(jìn)程被創(chuàng)建的時候,它其實是一個PID和TGID數(shù)值相同線程。當(dāng)線程A啟動線程B時,線程B會有自己的唯一PID,但它的TGID會從A繼承而來。這樣通過PID線程可以獨立得到調(diào)度,而相同的TGID可以知道哪些線程屬于同一個進(jìn)程,這樣可以共享資源(RAM,虛擬內(nèi)存、文件等)。

          線程進(jìn)程的區(qū)別體現(xiàn)在6個方面:

          • 根本區(qū)別:進(jìn)程是操作系統(tǒng)資源分配的基本單位,而線程是處理器任務(wù)調(diào)度和執(zhí)行的基本單位。

          • 資源開銷:每個進(jìn)程都有獨立的代碼和數(shù)據(jù)空間,程序之間的切換會有較大的開銷;線程可以看做輕量級的進(jìn)程,同一進(jìn)程的線程共享代碼和數(shù)據(jù)空間,每個線程都有自己獨立的運行棧和程序計數(shù)器,線程之間切換的開銷小。

          • 包含關(guān)系:如果一個進(jìn)程內(nèi)有多個線程,則執(zhí)行過程不是一條線的,而是多條線(線程)共同完成的。

          • 內(nèi)存分配:同一進(jìn)程的線程共享本進(jìn)程的地址空間和資源,而進(jìn)程之間的地址空間和資源是相互獨立的。

          • 影響關(guān)系:一個進(jìn)程崩潰后,在保護(hù)模式下不會對其他進(jìn)程產(chǎn)生影響,但是一個線程崩潰整個進(jìn)程都死掉。所以多進(jìn)程要比多線程健壯。

          • 執(zhí)行過程:每個獨立的進(jìn)程有程序運行的入口、順序執(zhí)行序列和程序出口。但是線程不能獨立執(zhí)行,必須依存在應(yīng)用程序中,由應(yīng)用程序提供多個線程執(zhí)行控制。兩者均可并發(fā)執(zhí)行。

          協(xié)程與線程的區(qū)別

          1. 一個線程可以有多個協(xié)程。

          2. 大多數(shù)業(yè)務(wù)場景下,線程進(jìn)程可以看做是同步機(jī)制,而協(xié)程則是異步。

          3. 線程是搶占式,而協(xié)程是非搶占式的,所以需要用戶代碼釋放使用權(quán)來切換到其他協(xié)程,因此同一時間其實只有一個協(xié)程擁有運行權(quán),相當(dāng)于單線程的能力。

          4. 協(xié)程并不是取代線程,而且抽象于線程之上。線程是被分割的CPU資源, 協(xié)程是組織好的代碼流程, 協(xié)程需要線程來承載運行。

          進(jìn)程間的通信方式(IPC)

          每個進(jìn)程各自有不同的用戶地址空間,任何一個進(jìn)程的全局變量在另一個進(jìn)程中都看不到,所以進(jìn)程之間要交換數(shù)據(jù)必須通過內(nèi)核,在內(nèi)核中開辟一塊緩沖區(qū),進(jìn)程1把數(shù)據(jù)從用戶空間拷到內(nèi)核緩沖區(qū),進(jìn)程2再從內(nèi)核緩沖區(qū)把數(shù)據(jù)讀走,內(nèi)核提供的這種機(jī)制稱為進(jìn)程間通信(IPC,InterProcess Communication)

          Linux IPC的主要方式

          1.管道(pipe)

          管道,通常指無名管道,是UNIX系統(tǒng)IPC最古老的形式。

          管道是一種半雙工(即數(shù)據(jù)只能在一個方向上流動)的通信方式,數(shù)據(jù)只能單向流動,而且只能在具有親緣關(guān)系的進(jìn)程間使用。

          進(jìn)程的親緣關(guān)系指的是父子進(jìn)程或者兄弟進(jìn)程關(guān)系。

          當(dāng)一個管道建立時,它會創(chuàng)建兩個文件描述符:fd[0]為讀而打開,fd[1]為寫而打開。

          特點:

          1. 面向字節(jié)流,

          2. 生命周期隨內(nèi)核。

          3. 自帶同步互斥機(jī)制。

          4. 半雙工,單向通信,兩個管道實現(xiàn)雙向通信。

          2.命名管道(namedpipe)

          FIFO,也稱為命名管道,它是一種文件類型,也是半雙工的通信方式。多個進(jìn)程都可以通過一個約定好的名字找到同一個管道。FIFO允許無親緣關(guān)系進(jìn)程間的通信。FIFO的通信方式類似于在進(jìn)程中使用文件來傳輸數(shù)據(jù),只不過FIFO類型文件同時具有管道的特性。在數(shù)據(jù)讀出時,F(xiàn)IFO管道中同時清除數(shù)據(jù),并且“先進(jìn)先出”。

          3.消息隊列(messagequeue)

          消息隊列是由消息的鏈表,存放在內(nèi)核中并由消息隊列標(biāo)識符標(biāo)識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點。

          特點:

          1. 消息隊列可以認(rèn)為是一個全局的一個鏈表,鏈表節(jié)點鐘存放著數(shù)據(jù)報的類型和內(nèi)容,有消息隊列的標(biāo)識符進(jìn)行標(biāo)記。

          2. 消息隊列允許一個或多個進(jìn)程寫入或者讀取消息。

          3. 消息隊列的生命周期隨內(nèi)核。

          4. 消息隊列可實現(xiàn)雙向通信。

          但是當(dāng)發(fā)送到消息隊列的信息量大或操作頻繁的場合,需要拷貝的時間也就越多,此時可以采用共享內(nèi)存通信。

          4.共享內(nèi)存(shared memory)

          共享內(nèi)存就是映射一段能被其他進(jìn)程所訪問的內(nèi)存,這段共享內(nèi)存由一個進(jìn)程創(chuàng)建,但多個進(jìn)程都可以訪問。

          共享內(nèi)存是最快的IPC方式,它是針對其他進(jìn)程間通信方式運行效率低而專門設(shè)計的。它往往與其他通信機(jī)制(如信號量)配合使用來實現(xiàn)進(jìn)程間的同步和通信。

          特點:

          1. 不用從用戶態(tài)到內(nèi)核態(tài)的頻繁切換和拷貝數(shù)據(jù),直接從內(nèi)存中讀取就可以。

          2. 共享內(nèi)存是臨界資源,所以需要操作時必須要保證原子性。使用信號量或者互斥鎖都可以。

          3. 生命周期隨內(nèi)核。

          5.信號量(semophore)

          信號量是一個計數(shù)器,可以用來控制多個進(jìn)程對共享資源的訪問。它常作為一種鎖機(jī)制,防止某進(jìn)程正在訪問共享資源時,其他進(jìn)程也訪問該資源。因此,主要作為進(jìn)程間以及同一進(jìn)程內(nèi)不同線程之間的同步手段。

          信號量主要實現(xiàn)進(jìn)程之間的同步和互斥,而不是存儲通信內(nèi)容。

          信號量定義了兩種操作,p操作和v操作,p操作為申請資源,會將數(shù)值減去M,表示這部分被他使用了,其他進(jìn)程暫時不能用。v操作是歸還資源操作,告知歸還了資源可以用這部分。

          6.信號(signal)

          信號是軟件中斷產(chǎn)生,用于進(jìn)程間異步傳遞信息。信號可以用來直接進(jìn)行用戶空間進(jìn)程和內(nèi)核進(jìn)程之間的交互,內(nèi)核進(jìn)程也可以利用它來通知用戶空間進(jìn)程發(fā)生了哪些系統(tǒng)事件。

          一般在shell中操作,進(jìn)程獲取信號進(jìn)行處理,一共有64種信號,在shell中輸入 kill -l 可查閱

          7.套接字(socket)

          套接字(有的時候被譯為插座)也是一種進(jìn)程間通信機(jī)制,與其他通信機(jī)制不同的是,套接字允許兩個進(jìn)程進(jìn)行通訊,這兩個進(jìn)程可能運行在同一個機(jī)器上,也可能運行在不同機(jī)器上。

          相對于共享內(nèi)存可以多對多的讀取與寫入,套接字只能一對一。此外由于序列化等操作占用大量資源,相對于共享內(nèi)存,套接字更適合傳輸少量數(shù)據(jù)。

          進(jìn)程通信方式總結(jié)

          1. 管道:速度慢,容量有限,只有父子進(jìn)程能通訊

          2. 命名管道:任何進(jìn)程間都能通訊,但速度慢

          3. 消息隊列:容量受到系統(tǒng)限制,且要注意第一次讀的時候,要考慮上一次沒有讀完數(shù)據(jù)的問題

          4. 共享內(nèi)存:能夠很容易控制容量,速度快,但要保持同步,比如一個進(jìn)程在寫的時候,另一個進(jìn)程要注意讀寫的問題,相當(dāng)于線程中的線程安全問題。

          5. 信號量:不能傳遞復(fù)雜消息,只能用來同步。

          6. 信號:用于通知接收進(jìn)程某個事件已經(jīng)發(fā)生。

          7. 套接字:可用于不同機(jī)器之間的進(jìn)程間通信。

          線程間的通信方式

          鎖(Lock)

          鎖機(jī)制包括互斥鎖、條件變量、讀寫鎖。

          1. 互斥鎖提供了以排他方式防止數(shù)據(jù)結(jié)構(gòu)被并發(fā)修改的方法。

          2. 讀寫鎖允許多個線程同時讀共享數(shù)據(jù),而對寫操作是互斥的。

          3. 條件變量可以以原子的方式阻塞進(jìn)程,直到某個特定條件為真為止。對條件的測試是在互斥鎖的保護(hù)下進(jìn)行的。條件變量始終與互斥鎖一起使用。

          有關(guān)Java的鎖機(jī)制,可以點擊查看《詳解Java多線程鎖之synchronized》和《詳解Java多線程鎖之Lock和ReadWriteLock

          有關(guān)條件變量,可以點擊查看《Java多線程的可見性與有序性》中有關(guān)volatile的講解。

          信號量(Semaphore)

          可以查看這篇博客《快速了解基于AQS實現(xiàn)的Java并發(fā)工具類》中有關(guān)Semaphore的講解,感受下信號量如何在java線程通信中的使用。

          信號(Signal)

          可以查看這篇博客:《徹底搞懂Java的等待-通知(wait-notify)機(jī)制

          協(xié)程間的通信方式

          與線程不同,協(xié)程使用程序自定義的調(diào)度器進(jìn)行調(diào)度,因此更容易控制協(xié)程之間的執(zhí)行順序,要想充分利用協(xié)程的調(diào)度模型,有一個完備的通信機(jī)制是很重要的。它主要應(yīng)該有以下的功能:

          1. 能從一個協(xié)程發(fā)送消息到另一個協(xié)程,通知另一個協(xié)程特定的事件已經(jīng)發(fā)生。

          2. 能夠讓協(xié)程在事件未發(fā)生之前掛起,等待事件發(fā)生后被調(diào)度并處理,從而有效讓出CPU時間。

          3. 能夠在消息中附帶相應(yīng)的數(shù)據(jù)。

          能完成這樣任務(wù)的模型很多,原理也不盡相同,但思路其實和線程的通信方式大體相同,這里以后再單獨講解。

          補(bǔ)充

          Nginx的進(jìn)程通信有哪些

          Nginx的進(jìn)程通信分為三種類別:linux系統(tǒng)與Nginx通信(信號),master進(jìn)程與worker進(jìn)程通信(套接字),worker進(jìn)程間通信(共享內(nèi)存)。

          1. linux系統(tǒng)與Nginx通信
            答:linux系統(tǒng)與Nginx是通過信號進(jìn)行通信的,通過信號控制Nginx重啟、關(guān)閉以及加載配置文件等。比如:./nginx –s quit 向master進(jìn)程發(fā)送信號。

          2. master進(jìn)程與worker進(jìn)程通信
            答:master在fork worker進(jìn)程前,先調(diào)用socketpair,創(chuàng)建一個socket對用來master與worker進(jìn)程間的通信。這個socket就是一個元素個數(shù)為2的數(shù)組channel,channel[0]用于master進(jìn)程寫入,channel[1]用于worker進(jìn)程讀入。

          3. worker進(jìn)程間通信
            答:共享內(nèi)存是最快的通信方式,是worker進(jìn)程之間的通信方式。使用共享內(nèi)存的好處是當(dāng)多個進(jìn)程使用同一塊共享內(nèi)存時,在任何一個進(jìn)程修改了共享內(nèi)存中的內(nèi)容后,其他進(jìn)程通過訪問這段共享內(nèi)存都能夠得到修改后的內(nèi)容。

          進(jìn)程七態(tài)

          各種狀態(tài)的意義:

          • 創(chuàng)建態(tài):進(jìn)程正在被創(chuàng)建。

          • 就緒態(tài):可運行,但因為其他進(jìn)程正在運行而暫時停止。

          • 運行態(tài):正在占用CPU。

          • 結(jié)束態(tài):進(jìn)程正在從系統(tǒng)中消失。

          • 阻塞狀態(tài):該進(jìn)程等待某個事件(比如IO讀取)而停止運行,此時即使有CPU時間片也無法繼續(xù)運行。

          狀態(tài)變化事件:

          • NULL => 創(chuàng)建態(tài):一個進(jìn)程被創(chuàng)建時的第一個狀態(tài)。

          • 創(chuàng)建態(tài) => 就緒態(tài):當(dāng)進(jìn)程創(chuàng)建完成,進(jìn)入就緒態(tài)。

          • 就緒態(tài) => 運行態(tài):CPU從就緒隊列選擇進(jìn)程執(zhí)行,進(jìn)入運行態(tài)。

          • 運行態(tài) => 結(jié)束態(tài):當(dāng)進(jìn)程已經(jīng)運行完成或出錯時,進(jìn)入結(jié)束態(tài)。

          • 運行態(tài) => 就緒態(tài):分配給進(jìn)程的時間片使用完,進(jìn)入就緒態(tài)。

          • 運行態(tài) => 阻塞狀態(tài):進(jìn)程執(zhí)行等待事件,進(jìn)入阻塞態(tài)。

          • 阻塞狀態(tài) => 就緒態(tài):進(jìn)程事件完成,CPU收到中斷信號,進(jìn)入就緒態(tài)。

          進(jìn)程狀態(tài)變化中,還有一種狀態(tài)叫掛起態(tài),掛起態(tài)代表該進(jìn)程沒有占用內(nèi)存空間,這跟阻塞狀態(tài)是不一樣。

          掛起和阻塞的區(qū)別:

          • 掛起是一個行為,而阻塞是進(jìn)程的一種狀態(tài)。

          • 進(jìn)程存放的位置不同:掛起是將進(jìn)程移到外存中,而處于阻塞狀態(tài)的進(jìn)程還是在內(nèi)存中。

          • 原因不同:導(dǎo)致進(jìn)程被掛起的原因一般是內(nèi)存不足或者是系統(tǒng)、用戶的請求,協(xié)調(diào)、修改進(jìn)程,研究進(jìn)程的狀態(tài)等,進(jìn)程阻塞是進(jìn)程正在等待某一事件發(fā)生,可能是等待資源或者響應(yīng)等(eg.等待I/O完成等)而暫時停止運行。

          • 掛起對應(yīng)的行為是激活,將外存中的進(jìn)程調(diào)入內(nèi)存中。而處于阻塞狀態(tài)的進(jìn)程需要其他進(jìn)程或系統(tǒng)喚醒。

          • 掛起是被動的行為,進(jìn)程被迫從內(nèi)存中移至外存中。而進(jìn)入阻塞可以看成是一個主動的行為(eg.進(jìn)程I/O時,進(jìn)程在等待I/O設(shè)備完成時,進(jìn)程主動進(jìn)入阻塞狀態(tài),I/O完成,進(jìn)程被激活)

          掛起態(tài)可以分為下面兩種:

          • 阻塞掛起狀態(tài):進(jìn)程在外存(磁盤)并等待某個事件的出現(xiàn)。

          • 就緒掛起狀態(tài):進(jìn)程在外存(磁盤)激活后進(jìn)入就緒態(tài)。

          參考文檔:

          1. 《深入理解計算機(jī)系統(tǒng)》

          2. 《深入理解Nginx》


          瀏覽 65
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国内精品偷拍 | 欧美日本色| 亚洲欧美日韩一级 | 日本精品视频在线观看 | 强奸操逼视频网站 |