進程、線程、協(xié)程
本文將從“操作系統(tǒng)”、“Java應(yīng)用”上兩個角度來探究這三者的區(qū)別。
一、進程
在我本人的疑惑中,我有以下3個問題。
1.1為什么要引入進程?
在“多道程序環(huán)境下”,允許多個程序并發(fā)執(zhí)行,此時它們將失去封閉性,并具有間斷性以及不可再現(xiàn)性的特征,因此需要引入進程的概念。
1.2什么是進程?進程由什么構(gòu)成。
進程是程序執(zhí)行的過程 ,包括了動態(tài)創(chuàng)建、調(diào)度和消亡的的整個過程,進程是程序資源管理的最小單位。好比下列匯編代碼代碼所示,包含對程序資源的調(diào)度。
_add_a_and_b:
push %ebx
mov %eax, [%esp+8]
mov %ebx, [%esp+12]
add %eax, %ebx
pop %ebx
ret
_main:
push 3
push 2
call _add_a_and_b
add %esp, 8
ret
進程由三部分組成。
- 進程控制塊(PCB),是進程存在的唯一標識,
- 程序段
- 數(shù)據(jù)段
1.3Liunx進程實現(xiàn)
Linux 并沒有為線程準備特定的數(shù)據(jù)結(jié)構(gòu),因為 Linux只有task_struct這一種描述進程的結(jié)構(gòu)體。在內(nèi)核看來只有進程而沒有線程,線程調(diào)度時也是當做進程來調(diào)度的。Linux所謂的線程其實是與其他進程共享資源的輕量級進程。
為什么說是輕量級呢?在于它只有一個最小的執(zhí)行上下文和調(diào)度程序所需的統(tǒng)計信息,它只帶有進程執(zhí)行相關(guān)的信息,與父進程共享進程地址空間
二、線程
2.1線程是什么?
線程是操作操作系統(tǒng)能夠運行運算調(diào)度的最小單位。線程被包含在進程之中,是進程中的實際運作的單位,一個進程內(nèi)可以包含多個線程,線程是資源調(diào)度的最小單位。
在Liunx中,線程沒有特定的數(shù)據(jù)結(jié)構(gòu),如何區(qū)別開來線程與進程的創(chuàng)建呢,這根據(jù)創(chuàng)建時參數(shù)的不同來決定,例如線程只有一個最小的執(zhí)行上下文和調(diào)度程序所需的統(tǒng)計信息。
2.2線程擁有什么?
同一進程中的多條線程共享該進程中的 全部系統(tǒng)資源,如
- 虛擬地址空間
- 文件描述符號
- 信號處理
但是同一個進程的不同線程也有各自的信息,如
- 調(diào)用棧
- 寄存器環(huán)境
- 線程本次存儲
3.3線程分類
3.4 Java如何啟動一個線程
start– > start0 …..Native方法(由JVM中的c++調(diào)用)----> Liunx內(nèi)核的 pthread_create方法
三、協(xié)程
3.1 既然有多線程操作,為什么還要引入?yún)f(xié)程?
操作系統(tǒng)在線程等待IO的時候,會阻塞當前線程,切換到其他線程,這樣在當前線程等待IO的過程中,其他線程可以繼續(xù)執(zhí)行。這樣操作在系統(tǒng)線程較少的時候沒有多大問題,可是當線程數(shù)量非常多的時候,卻產(chǎn)生了問題。一是系統(tǒng)線程會占用非常多的內(nèi)存空間,二是過多的線程切換會占用大量的系統(tǒng)時間。
而協(xié)程剛好可以解決上述的兩個問題。
3.2 協(xié)程的概念
協(xié)程就是把原來每個線程分別負責(zé)的任務(wù)壓縮到少量線程中,每個線程中用協(xié)程來實現(xiàn)原來線程級別的任務(wù),因為包裝了系統(tǒng)io導(dǎo)致協(xié)程內(nèi)遇到io不會導(dǎo)致當前線程被掛起,以起到最大化利用時間片,減少線程調(diào)度開銷的作用。
協(xié)程運行在線程之上,當一個協(xié)程運行完成后,可以選擇主動讓出,讓另一個協(xié)程運行在當前線程之上。
- 協(xié)程并沒有增加線程數(shù)量,只是在線程的基礎(chǔ)之上通過分時復(fù)用的方式運行多個協(xié)程
- 協(xié)程的切換在用戶態(tài)完成,切換的代價比線程從用戶態(tài)到內(nèi)核臺的代價小很多。
3.3 協(xié)程的注意事項
實際上協(xié)程并不是什么銀彈,協(xié)程只有在等待IO的過程中才能重復(fù)利用線程,線程在等待IO的過程中會陷入阻塞狀態(tài)。
假設(shè)協(xié)程運行在線程之上,并且協(xié)程調(diào)用了一個阻塞IO操作,這時候會發(fā)生什么?實際上操作系統(tǒng)并不知道協(xié)程的存在,它只知道線程,因此在協(xié)程調(diào)用阻塞IO操作的時候,操作系統(tǒng)會讓線程進入阻塞狀態(tài),當前的協(xié)程和其它綁定在該線程之上的協(xié)程都會陷入阻塞而得不到調(diào)度,這往往是不能接受的。
3.4 Java中的應(yīng)用--虛擬線程
Java 19 已經(jīng)預(yù)2022年9月20日發(fā)布,虛擬線程是其中的一項預(yù)覽功能。文章來源:http://www.zghlxwxcb.cn/news/detail-480283.html
虛擬線程是輕量級的線程,它們不與操作系統(tǒng)線程綁定,而是由 JVM 來管理。它們適用于“每個請求一個線程”的編程風(fēng)格,同時沒有操作系統(tǒng)線程的限制。我們能夠創(chuàng)建數(shù)以百萬計的虛擬線程而不會影響吞吐。這與 Go 編程語言(Golang)的協(xié)程(如goroutines)非常相似。文章來源地址http://www.zghlxwxcb.cn/news/detail-480283.html
Thread.startVirtualThread(() -> {
System.out.println("Hello, Project Loom!");
});
到了這里,關(guān)于關(guān)于進程、線程、協(xié)程的概念以及Java中的應(yīng)用的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!