進程、線程、協(xié)程之間的演變

1.進程

1.1定義

進程是計算機中一個正在執(zhí)行的程序?qū)嵗?。進程是操作系統(tǒng)中最基本的執(zhí)行單元,它擁有自己的程序代碼、數(shù)據(jù)集合和執(zhí)行狀態(tài),并由操作系統(tǒng)管理和調(diào)度。

1.2內(nèi)容

進程通常由程序、數(shù)據(jù)集合和進程控制塊三部分組成。

  1. 程序,是進程的代碼部分,它是計算機程序的執(zhí)行體現(xiàn)。程序通常由指令和數(shù)據(jù)組成,它們被存儲在進程的內(nèi)存空間中,并由 CPU 執(zhí)行。

  2. 數(shù)據(jù)集合包括進程所需的所有數(shù)據(jù),例如變量、數(shù)組、對象等。數(shù)據(jù)集合通常也被存儲在進程的內(nèi)存空間中,它們可以被程序訪問和修改。

  3. 進程控制塊(Process Control Block,PCB)是操作系統(tǒng)用來管理進程的數(shù)據(jù)結(jié)構(gòu)。它包含了進程的狀態(tài)、進程標識符、程序計數(shù)器、內(nèi)存管理信息、進程優(yōu)先級等信息。操作系統(tǒng)可以使用進程控制塊來管理和調(diào)度進程,例如創(chuàng)建和終止進程、切換進程的執(zhí)行等。

1.3特征

輔助記憶

  • 進程開始前:動態(tài)性(可動態(tài)創(chuàng)建、調(diào)度和終止)、獨立性(擁有獨立的內(nèi)存空間、資源和當前執(zhí)行狀態(tài))、共享性(進程運行與操作系統(tǒng)中,因此文件、消息隊列、信號量等用于對進程控制,且具備共享屬性)
  • 進程開始中:并發(fā)性(可以多個進程并發(fā)運行,承托于cpu)、異步性(由于可并發(fā),所以對于CPU、公共內(nèi)存、I/O等是互相爭奪的)
  1. 動態(tài)性:進程是一個動態(tài)的概念,它代表了一個正在執(zhí)行的程序?qū)嵗?,可以?chuàng)建、調(diào)度和終止。在操作系統(tǒng)中,進程的創(chuàng)建和銷毀是動態(tài)進行的。

  2. 并發(fā)性:在操作系統(tǒng)中,可以同時存在多個進程在執(zhí)行,它們之間是并發(fā)執(zhí)行的。操作系統(tǒng)可以通過進程調(diào)度算法來協(xié)調(diào)多個進程之間的執(zhí)行,從而實現(xiàn)對系統(tǒng)資源的高效利用。

  3. 獨立性:進程是操作系統(tǒng)中的獨立執(zhí)行單元,每個進程都有自己獨立的內(nèi)存空間、資源和執(zhí)行狀態(tài),不會受到其他進程的影響。

  4. 異步性:不同進程之間的執(zhí)行速度是不同的,它們可以相互競爭系統(tǒng)資源,例如 CPU、內(nèi)存、I/O 設(shè)備等。進程之間的執(zhí)行順序是不可預(yù)測的,需要通過操作系統(tǒng)的調(diào)度算法進行管理。

  5. 共享性:進程之間可以共享系統(tǒng)資源,例如文件、消息隊列、信號量等。操作系統(tǒng)提供了各種機制來協(xié)調(diào)進程之間的資源共享,從而實現(xiàn)對系統(tǒng)資源的高效利用。

1.4梳理

image.png

2.線程

2.1定義

線程是操作系統(tǒng)中能夠被調(diào)度的最小執(zhí)行單元。一個進程可以包含多個線程,每個線程都是獨立的執(zhí)行流程,擁有自己的程序計數(shù)器、棧和局部變量等線程上下文信息,但共享進程的代碼、數(shù)據(jù)和全局變量等資源。

2.2由來

任務(wù)調(diào)度:任務(wù)調(diào)度是操作系統(tǒng)中的一種機制,它用于協(xié)調(diào)和管理系統(tǒng)中的各種任務(wù)或進程的執(zhí)行順序和優(yōu)先級。任務(wù)調(diào)度器會根據(jù)一定的策略,將CPU時間片分配給需要執(zhí)行的任務(wù)或進程,以實現(xiàn)高效的系統(tǒng)資源利用和響應(yīng)性能。

在任務(wù)調(diào)度的過程中,操作系統(tǒng)會根據(jù)不同的調(diào)度算法來確定任務(wù)的執(zhí)行順序和優(yōu)先級。常見的調(diào)度算法包括先來先服務(wù)(FCFS)、最短作業(yè)優(yōu)先(SJF)、優(yōu)先級調(diào)度、時間片輪轉(zhuǎn)等。

在早期的操作系統(tǒng)中并沒有線程的概念,進程是能擁有資源和獨立運行的最小單位,也是程序執(zhí)行的最小單位。任務(wù)調(diào)度采用的是時間片輪轉(zhuǎn)的搶占式調(diào)度方式,而進程是任務(wù)調(diào)度的最小單位,每個進程有各自獨立的一塊內(nèi)存,使得各個進程之間內(nèi)存地址相互隔離。后來,隨著計算機的發(fā)展,對CPU的要求越來越高,進程之間的切換開銷較大,已經(jīng)無法滿足越來越復雜的程序的要求了,于是就發(fā)明了線程。

2.3內(nèi)容

線程通常由線程 ID、程序計數(shù)器、寄存器集合、棧和狀態(tài)等組成。

  1. 線程 ID:每個線程都有一個唯一的線程 ID,用于區(qū)分不同的線程。

  2. 程序計數(shù)器:程序計數(shù)器是一個指針,用于記錄當前線程執(zhí)行的位置。當線程被暫?;蚯袚Q時,程序計數(shù)器的值會保存到線程控制塊中,以便下次恢復執(zhí)行。

  3. 寄存器集合:線程也擁有自己的寄存器集合,用于保存線程的局部變量和其他狀態(tài)信息。

  4. 棧:每個線程都有自己的棧,用于保存函數(shù)調(diào)用時的參數(shù)、返回地址和局部變量等信息。線程棧通常比進程棧小得多,因為線程不需要保存進程的所有狀態(tài)信息。

  5. 狀態(tài):線程可以處于就緒、運行、等待或結(jié)束等不同的狀態(tài)。就緒狀態(tài)表示線程可以立即執(zhí)行,等待狀態(tài)表示線程需要等待某些條件滿足才能執(zhí)行,運行狀態(tài)表示線程正在執(zhí)行,結(jié)束狀態(tài)表示線程已經(jīng)完成執(zhí)行。

java線程狀態(tài)圖:線程狀態(tài)圖-參考博客

線程狀態(tài)圖

2.3.1Java棧

Java棧是Java虛擬機中的一種重要數(shù)據(jù)結(jié)構(gòu),用于存儲方法調(diào)用的信息,包括局部變量、方法參數(shù)、返回值等。每個線程在運行時都會有一個對應(yīng)的Java棧。

Java棧中的每個元素稱為棧幀(Stack Frame),用于保存方法調(diào)用的上下文信息。棧幀中包含了局部變量表、操作數(shù)棧、返回地址和異常處理表等信息。

棧的數(shù)據(jù)結(jié)構(gòu)

圖片來源

2.3.2幀棧

寄存器的使用

在x86架構(gòu)的CPU中,棧通常從高地址向低地址增長。通用寄存器(General Purpose Registers):包括eax、ebx、ecx、edx、esi、edi、ebp、esp等8個寄存器。

  1. ebp寄存器(Extended Base Pointer Register):通常用于指向當前棧幀的基地址(Base Address)

  2. esp寄存器(Extended Stack Pointer Register):通常用于指向棧頂指針

  3. ebx寄存器(Extended Base Register):通常用作指針,保存內(nèi)存地址,也用于存儲函數(shù)調(diào)用的返回值。

  4. edi寄存器(Destination Index Register):通常用于存儲目標地址,例如字符串復制等操作。

  5. esi寄存器(Source Index Register):通常用于存儲源地址,例如字符串比較等操作。

操作流程:

調(diào)用方法時,會將當前棧幀壓入虛擬機棧中,然后創(chuàng)建新的棧幀,并將ebp和esp寄存器設(shè)置為新棧幀的基地址和棧頂指針。

返回方法時,會彈出當前棧幀,并將ebp和esp寄存器恢復為上一個棧幀的基地址和棧頂指針。

參考博客

int main()
{
    int a = 10;
    int b = 20;
    int c = 0;
    c = max(a, b);
    printf( "%d\n", c);
    system( "pause");
    return 0;
}
int max(int x, int y)
{
    int z = 0;
    if (x > y)
        z = x;
    else
        z = y;
    return z;
}

執(zhí)行順序:

1.esp和ebp分別先指向main()的棧幀基地址和棧頂

2.從棧底向棧頂方向壓入,分別是參數(shù)、返回地址、main的返回地址、main的ebp基地址

3.最后棧頂會分別壓入ebx、esi、edi寄存器


棧幀中包含了局部變量表、操作數(shù)棧、返回地址和異常處理表等信息。

棧幀內(nèi)容

棧幀中包含了局部變量表、操作數(shù)棧、返回地址和異常處理表等信息。

  1. 局部變量表:用于存儲方法中定義的局部變量,包括基本數(shù)據(jù)類型和對象引用等,以索引的方式訪問,從0開始。

  2. 操作數(shù)棧:用于存儲操作數(shù)和返回值,通常使用先進先出(FIFO)的方式進行操作。

  3. 返回地址:用于保存方法調(diào)用完成后返回的地址,以便程序跳轉(zhuǎn)回原來的調(diào)用點繼續(xù)執(zhí)行。

  4. 異常處理表:用于保存方法執(zhí)行過程中可能拋出的異常處理信息,以便在發(fā)生異常時進行處理。

操作數(shù)棧補充:

Java虛擬機規(guī)范中規(guī)定,每個操作數(shù)棧的最大深度不能超過255個棧單元。如果超過了這個限制,將會拋出StackOverflowError異常。操作數(shù)棧的大小受到Java虛擬機內(nèi)存分配的限制,如果內(nèi)存不足,也會拋出OutOfMemoryError異常。

復現(xiàn)方式:無限遞歸回調(diào)

2.4梳理

3.協(xié)程

3.1定義

協(xié)程,英文Coroutines,是一種基于線程之上,比線程更加輕量級的存在,這種由程序員自己寫程序來管理的輕量級線程叫做『用戶空間線程』,具有對內(nèi)核來說不可見的特性。

概念補充:

  • 內(nèi)核線程:由操作系統(tǒng)內(nèi)核創(chuàng)建和管理的一種線程,即跟CPU的物理核數(shù)相關(guān)

  • 超線程技術(shù)(Hyper-Threading Technology):是一種基于硬件的多線程技術(shù),將單個物理處理器中增加一個線程調(diào)度器和一組寄存器,用于存儲多個線程的上下文信息,以此實現(xiàn)并行執(zhí)行多個線程的效果。

3.2由來

多線程的缺點

  1. 復雜度增加:多線程編程需要考慮線程之間的同步、互斥、協(xié)作等問題,如鎖、信號量、條件變量等,增加了程序的復雜度和開發(fā)難度。

  2. 死鎖和競態(tài)條件:多線程之間共享內(nèi)存區(qū)域,容易發(fā)生死鎖、競態(tài)條件等問題,導致程序的不穩(wěn)定性和異常終止。

  3. 資源消耗增加:每個線程都需要一定的系統(tǒng)資源,如內(nèi)存、文件句柄、網(wǎng)絡(luò)連接等,大量的線程會導致系統(tǒng)資源的耗盡和浪費。

  4. 上下文切換開銷:線程之間的切換需要進行上下文的保存和恢復,會增加系統(tǒng)開銷和延遲,影響程序的性能和響應(yīng)速度。

協(xié)程的優(yōu)點

  1. 快速切換:相比線程,協(xié)程沒有自己的調(diào)度器和上下文切換,協(xié)程通常采用生成器(Generator)或異步生成器(Async Generator)實現(xiàn)快速切換。生成器是一種特殊的函數(shù),可以通過yield關(guān)鍵字暫停函數(shù)的執(zhí)行,并返回一個中間結(jié)果,然后在需要的時候重新開始執(zhí)行。異步生成器是一種特殊的生成器,可以在異步環(huán)境下使用,例如在事件循環(huán)中實現(xiàn)異步操作。

  2. 開銷輕量:線程的默認Stack大小是1M,而協(xié)程接近1K,因此可減少多線程的系統(tǒng)資源開銷。

  3. 低復雜度:線程的復雜度訪問共有內(nèi)存數(shù)據(jù)時,需要考慮鎖、信號量、條件變量等,由此衍生出死鎖和各種競爭狀態(tài),協(xié)程由于生成器是一種特殊的等待函數(shù),可實現(xiàn)同步返回和恢復執(zhí)行,且異步生成器則是異步返回和恢復執(zhí)行,由此解決多線程網(wǎng)絡(luò)通信、I/O操作等的死鎖和競爭問題。

3.3原理

  • 生成器:一種同步的生成器,它通過yield關(guān)鍵字來逐步生成數(shù)據(jù)。在生成器函數(shù)中,當執(zhí)行到y(tǒng)ield語句時,生成器會將當前狀態(tài)保存下來,并將yield語句后面的值返回給調(diào)用方。當調(diào)用方需要獲取下一個元素時,生成器會恢復之前保存的狀態(tài),并從上一次的yield語句處繼續(xù)執(zhí)行,生成下一個元素。生成器的應(yīng)用場景主要是處理大量數(shù)據(jù)的場景,例如數(shù)據(jù)分頁、數(shù)據(jù)轉(zhuǎn)換等。

  • 異步生成器:異步生成器是基于異步迭代器(Async Iterator)實現(xiàn)的,可以處理異步的數(shù)據(jù)源。當異步生成器需要生成下一個元素時,它會暫停當前的協(xié)程執(zhí)行,等待異步數(shù)據(jù)源返回數(shù)據(jù)后再生成下一個元素。異步生成器的應(yīng)用場景主要是處理異步數(shù)據(jù)源、網(wǎng)絡(luò)通信等場景。

協(xié)程最重要的特點是支持掛起和恢復操作。在協(xié)程中,可以通過掛起函數(shù)將協(xié)程掛起,并將協(xié)程的狀態(tài)保存下來,以便后續(xù)恢復執(zhí)行。協(xié)程的掛起和恢復是由程序員手動控制的,因此可以更靈活地控制程序的執(zhí)行順序和并發(fā)度。

3.4梳理


博客參考:

https://www.cnblogs.com/Survivalist/p/11527949.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容