Java線程模型
本文將從線程類型笔喉、線程通信洲鸠、線程調(diào)度三個(gè)方面分析Java中的線程模型。
什么是線程教馆?
線程就是進(jìn)程的切片。因?yàn)镃PU速度太快擂达,進(jìn)程切換時(shí)cpu都要進(jìn)行進(jìn)程上下文的加載土铺、保存操作。對(duì)CPU來說是巨大的性能浪費(fèi)板鬓。所以引入線程的目的就是為了細(xì)化進(jìn)程對(duì)CPU時(shí)間占用粒度悲敷,更加充分的利用CPU。
因?yàn)榫€程是對(duì)進(jìn)程的切片俭令,所以線程是共享進(jìn)程資源的后德,同一進(jìn)程里線程的切換不會(huì)影響進(jìn)程的切換。
與進(jìn)程的區(qū)別
- 進(jìn)程是資源分配的最小單位,線程是調(diào)度的最小單位抄腔。
- 進(jìn)程獨(dú)占資源瓢湃,線程共享進(jìn)程資源。
線程的類型
內(nèi)核線程(KLT)
內(nèi)核線程就是直接由操作系統(tǒng)內(nèi)核支持的線程赫蛇,這種線程由內(nèi)核來完成線程切換绵患,內(nèi)核通過操縱調(diào)度器對(duì)線程進(jìn)行調(diào)度,并負(fù)責(zé)將線程的任務(wù)映射到各個(gè)處理器上悟耘。每個(gè)內(nèi)核線程可以視為內(nèi)核的一個(gè)分身落蝙,這樣操作系統(tǒng)就有能力同時(shí)處理多件事情,支持多線程的內(nèi)核就叫做多線程內(nèi)核暂幼。
輕量級(jí)進(jìn)程(LWP)
輕量級(jí)進(jìn)程是由系統(tǒng)提供給用戶的操作內(nèi)核線程的接口的實(shí)現(xiàn)筏勒。即輕量級(jí)進(jìn)程是內(nèi)核線程的一個(gè)替身。
用戶線程(UT)
用戶線程建立在用戶空間的線程庫(kù)上旺嬉,系統(tǒng)內(nèi)核不能感知線程存在的實(shí)現(xiàn)管行。用戶線程的建立、同步邪媳、銷毀和調(diào)度完全在用戶態(tài)中完成病瞳,不需要內(nèi)核的幫助揽咕。如果程序?qū)崿F(xiàn)得當(dāng),這種線程不需要切換到內(nèi)核態(tài)套菜,因此操作可以是非城咨疲快速且低消耗的,也可以支持規(guī)模更大的線程數(shù)量逗柴,部分高性能數(shù)據(jù)庫(kù)中的多線程就是由用戶線程實(shí)現(xiàn)的蛹头。
線程模型
一對(duì)一模型
一對(duì)一模型即輕量級(jí)進(jìn)程的實(shí)現(xiàn)模式。一個(gè)LWP對(duì)應(yīng)一個(gè)KLT戏溺。
優(yōu)點(diǎn):每個(gè)LWP都是獨(dú)立的調(diào)度單元渣蜗,一個(gè)線程阻塞不影響其他線程。
缺點(diǎn):因?yàn)榕cKLT一對(duì)一旷祸。而KLT創(chuàng)建耕拷,調(diào)度需要一定內(nèi)核資源,因此創(chuàng)建數(shù)量有限托享。
一對(duì)多模型
一對(duì)多模型及用戶線程實(shí)現(xiàn)方式骚烧。一個(gè)進(jìn)程對(duì)應(yīng)多個(gè)UT。
優(yōu)點(diǎn):線程的管理在用戶空間進(jìn)行闰围。比較高效赃绊。
缺點(diǎn):需要用戶自己考慮線程的調(diào)度相關(guān)問題,因?yàn)橄到y(tǒng)對(duì)UT無感知羡榴,所以一個(gè)線程阻塞會(huì)導(dǎo)致進(jìn)程阻塞碧查。
多對(duì)多模型
在一對(duì)多的基礎(chǔ)上引入KLT。即一個(gè)進(jìn)程管理多個(gè)KLT校仑,KLT對(duì)應(yīng)多個(gè)UT忠售。
將 n 個(gè)UT映射到m個(gè)KLT上,要求 m <= n迄沫。
優(yōu)點(diǎn): 集合了前兩種模型的優(yōu)點(diǎn)档痪,去掉了他們的缺點(diǎn)。
缺點(diǎn):全是優(yōu)點(diǎn)邢滑。
線程的調(diào)度方式
搶占式調(diào)度
每個(gè)線程由系統(tǒng)分配CPU時(shí)間腐螟,線程本身無法控制使用多次CPU時(shí)間。好處是線程的執(zhí)行時(shí)間是可控的困后,不會(huì)造成因?yàn)橐粋€(gè)線程導(dǎo)致進(jìn)程長(zhǎng)時(shí)間阻塞問題乐纸。
協(xié)同式調(diào)度
線程自己控制CPU時(shí)間。并且當(dāng)前線程執(zhí)行完畢后需要通知系統(tǒng)切換另外一個(gè)線程摇予。最主要的問題是線程的切換取決于線程本身汽绢,若線程存在Bug導(dǎo)致切換線程不成功則會(huì)一直阻塞。
線程間通信與同步
線程雖然可以獨(dú)立的執(zhí)行侧戴。但是總會(huì)有需要不同的線程互相配合的情況宁昭,這就涉及到線程的通信與同步跌宛。目前有兩種方式。
共享內(nèi)存
共享內(nèi)存的并發(fā)模型里線程通過顯示的同步即通過互斥實(shí)現(xiàn)對(duì)公共空間的讀寫积仗,將需要共享的數(shù)據(jù)同步到公共的內(nèi)存中疆拘,這樣便實(shí)現(xiàn)了間接的通信。即共享內(nèi)存是顯示同步寂曹,隱式通信哎迄。
消息傳遞
消息傳遞模型即消息傳遞,線程間無公共內(nèi)存隆圆,因?yàn)橄⑼ㄐ盘烊痪哂邢群箨P(guān)系所以間接實(shí)現(xiàn)類數(shù)據(jù)的同步漱挚。所以消息傳遞模型是顯示通信,隱式同步渺氧。
Java中的線程
線程模型
目前Java默認(rèn)使用的是一對(duì)一模型旨涝。即LWP方案。不過在支持多對(duì)多的平臺(tái)上可以通過JVM參數(shù)控制使用多對(duì)多模型侣背。
相關(guān)參數(shù)
-XX:+UseLWPSynchronization(默認(rèn)值)
-XX:+UseBoundThreads
調(diào)度方式
Java采用搶占式調(diào)度白华。同時(shí)Java定義了10中線程優(yōu)先級(jí)⊥翰龋可以在一定程度上調(diào)整線程的CPU時(shí)間。
通信機(jī)制
Java采用的是共享內(nèi)存并發(fā)模型业筏。具體可參考Java內(nèi)存模型憔杨。
參考
- <<深入理解Java虛擬機(jī): JVM高級(jí)特性與最佳實(shí)踐>>
- <<Java并發(fā)編程的藝術(shù)>>