基本模型
由于Java 中,JVM主要是由C/C++實(shí)現(xiàn),所以Java層線(xiàn)程最終還是會(huì)映射到JVM層線(xiàn)程,而Java層的線(xiàn)程到操作系統(tǒng)層線(xiàn)程就得需要看具體的JVM的具體實(shí)現(xiàn)來(lái)決定。
一般來(lái)說(shuō),我們都把用戶(hù)線(xiàn)程看作更高層面的線(xiàn)程,而內(nèi)核線(xiàn)程則向用戶(hù)線(xiàn)程提供支持。
由此可見(jiàn),用戶(hù)線(xiàn)程和內(nèi)核線(xiàn)程之間必然存在一定的映射關(guān)系,不同的操作系統(tǒng)可能采取不同的映射方式。
一般來(lái)說(shuō),按照映射方式來(lái)看,主要可以分為:多對(duì)一映射(用戶(hù)級(jí)方式),一對(duì)一映射(內(nèi)核級(jí)方式) 和多對(duì)多映射(組合方式)3種方式。其中:
1. 多對(duì)一映射(用戶(hù)級(jí)方式)
多對(duì)一映射是指多個(gè)用戶(hù)線(xiàn)程被映射到一個(gè)內(nèi)核線(xiàn)程上。每一個(gè)進(jìn)程都對(duì)應(yīng)著一個(gè)內(nèi)核線(xiàn)程,進(jìn)程內(nèi)的所有線(xiàn)程也都對(duì)應(yīng)著該內(nèi)核線(xiàn)程。
多對(duì)一映射模型是指多條用戶(hù)線(xiàn)程映射同一條內(nèi)核線(xiàn)程的情況,其中用戶(hù)線(xiàn)程由庫(kù)調(diào)度器進(jìn)行調(diào)度,而內(nèi)核線(xiàn)程由操作系統(tǒng)調(diào)度器來(lái)完成。
對(duì)于用戶(hù)線(xiàn)程而言,其會(huì)按照一定的策略輪流執(zhí)行,具體的調(diào)度算法有庫(kù)調(diào)度器完成。
任意一個(gè)時(shí)刻每一個(gè)進(jìn)程中都只有一個(gè)用戶(hù)線(xiàn)程被執(zhí)行,它們的執(zhí)行都由用戶(hù)態(tài)的代碼完成切換。
在不支持線(xiàn)程的操作系統(tǒng)中有庫(kù)來(lái)實(shí)現(xiàn)線(xiàn)程控制,用戶(hù)線(xiàn)程創(chuàng)建,銷(xiāo)毀,切換的開(kāi)銷(xiāo)代價(jià)比內(nèi)核線(xiàn)程小。
因此,這種模式特點(diǎn)主要有兩點(diǎn):
首先,可以節(jié)省內(nèi)核態(tài)到用戶(hù)態(tài)切換的開(kāi)銷(xiāo)
其次,線(xiàn)程的數(shù)量不會(huì)受到內(nèi)核線(xiàn)程的限制
但是,因?yàn)榫€(xiàn)程切換的工作是由用戶(hù)態(tài)的代碼完成的,所以一個(gè)進(jìn)程內(nèi),如果當(dāng)一條線(xiàn)程發(fā)生阻塞時(shí),與該內(nèi)核線(xiàn)程對(duì)應(yīng)的進(jìn)程內(nèi)的其他所有的用戶(hù)線(xiàn)程也會(huì)一起陷入阻塞。
2. 一對(duì)一映射(內(nèi)核級(jí)方式)
一對(duì)一映射是指每個(gè)用戶(hù)線(xiàn)程都會(huì)被影射到一個(gè)內(nèi)核線(xiàn)程上,用戶(hù)的整個(gè)生命周期都綁定到所映射的內(nèi)核線(xiàn)程上。一個(gè)進(jìn)程內(nèi)可以有一個(gè)用戶(hù)線(xiàn)程和至少一個(gè)用戶(hù)線(xiàn)程,都對(duì)應(yīng)著各自一個(gè)和至少一個(gè)內(nèi)核線(xiàn)程,進(jìn)程內(nèi)的所有線(xiàn)程也都一一對(duì)應(yīng)著各自?xún)?nèi)核線(xiàn)程。
一對(duì)一映射模型是指一條用戶(hù)線(xiàn)程對(duì)應(yīng)著內(nèi)核中的一條線(xiàn)程的情況,其中用戶(hù)線(xiàn)程由庫(kù)調(diào)度器進(jìn)行調(diào)度,而內(nèi)核線(xiàn)程由操作系統(tǒng)調(diào)度器來(lái)完成,而Java中采用的就是這種模型。
在這種方式下,多個(gè)CPU能并行執(zhí)行同一個(gè)進(jìn)程內(nèi)的多個(gè)線(xiàn)程。
如果進(jìn)程內(nèi)的某個(gè)線(xiàn)程被阻塞,就可以切換到該進(jìn)程的其他線(xiàn)程繼續(xù)執(zhí)行,并且能切換執(zhí)行其他進(jìn)程的線(xiàn)程。
一對(duì)一映射模型是真正意義上的并行執(zhí)行,因?yàn)檫@種模型下,創(chuàng)建一條Java的Thread線(xiàn)程是真正的在內(nèi)核中創(chuàng)建并映射了一條內(nèi)核線(xiàn)程的,執(zhí)行過(guò)程中,一條線(xiàn)程不會(huì)因?yàn)榱硗庖粭l線(xiàn)程的原因而發(fā)生阻塞等情況。
不過(guò)因?yàn)槭敲恳粋€(gè)用線(xiàn)程都需要對(duì)應(yīng)一個(gè)內(nèi)核線(xiàn)程,這種直接映射內(nèi)核線(xiàn)程的模式,所以數(shù)量會(huì)存在上限。
并且同一個(gè)核心中,多條線(xiàn)程的執(zhí)行需要頻繁的發(fā)生上下文切換以及內(nèi)核態(tài)與用戶(hù)態(tài)之間的切換,所以如果線(xiàn)程數(shù)量過(guò)多,切換過(guò)于頻繁會(huì)導(dǎo)致線(xiàn)程執(zhí)行效率下降。
3. 多對(duì)多映射(組合方式)
多對(duì)多映射是指將一對(duì)一映射(內(nèi)核級(jí)方式)和多對(duì)一映射(用戶(hù)級(jí)方式)組合起來(lái),通過(guò)綜合兩者優(yōu)點(diǎn)來(lái)形成的一種映射方式。該方式在用戶(hù)空間創(chuàng)建,銷(xiāo)毀,切換,調(diào)度線(xiàn)程,但是進(jìn)程中的多個(gè)用戶(hù)線(xiàn)程會(huì)被影射到若干個(gè)內(nèi)核線(xiàn)程上。
多對(duì)多映射模型就可以避免上面一對(duì)一映射模型和多對(duì)一映射模型帶來(lái)的弊端,也就是多條用戶(hù)線(xiàn)程映射多條內(nèi)核線(xiàn)程,這樣即可以避免一對(duì)一映射模型的切換效率問(wèn)題和數(shù)量限制問(wèn)題,也可以避免多對(duì)一映射模型的阻塞問(wèn)題。
每一個(gè)內(nèi)核線(xiàn)程負(fù)責(zé)與之綁定的若干用戶(hù)線(xiàn)程,進(jìn)程中的某個(gè)線(xiàn)程發(fā)生系統(tǒng)阻塞并不會(huì)導(dǎo)致整個(gè)進(jìn)程阻塞,而阻塞該內(nèi)核線(xiàn)程內(nèi)的所對(duì)應(yīng)的若干用戶(hù)線(xiàn)程,其他線(xiàn)程依舊可以照常執(zhí)行。
同時(shí),因?yàn)橛脩?hù)線(xiàn)程數(shù)量比內(nèi)核線(xiàn)程數(shù)量多,所以能有效減少內(nèi)核線(xiàn)程開(kāi)銷(xiāo)。