溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

死磕 java線程系列之線程模型

發(fā)布時間:2020-07-18 04:33:28 來源:網(wǎng)絡(luò) 閱讀:154 作者:彤哥讀源碼 欄目:編程語言

問題

(1)線程有哪些類型?

(2)線程模型有哪些?

(3)各語言是怎么實現(xiàn)自己的線程模型的?

簡介

在Java中,我們平時所說的并發(fā)編程、多線程、共享資源等概念都是與線程相關(guān)的,這里所說的線程實際上應(yīng)該叫作“用戶線程”,而對應(yīng)到操作系統(tǒng),還有另外一種線程叫作“內(nèi)核線程”。

用戶線程位于內(nèi)核之上,它的管理無需內(nèi)核支持;而內(nèi)核線程由操作系統(tǒng)來直接支持與管理。幾乎所有的現(xiàn)代操作系統(tǒng),包括 Windows、Linux、Mac OS X 和 Solaris,都支持內(nèi)核線程。

最終,用戶線程和內(nèi)核線程之間必然存在某種關(guān)系,本章我們一起來學(xué)習(xí)下建立這種關(guān)系常見的三種方法:多對一模型、一對一模型和多對多模型。

多對一模型

死磕 java線程系列之線程模型

多對一線程模型,又叫作用戶級線程模型,即多個用戶線程對應(yīng)到同一個內(nèi)核線程上,線程的創(chuàng)建、調(diào)度、同步的所有細(xì)節(jié)全部由進(jìn)程的用戶空間線程庫來處理。

優(yōu)點(diǎn):

  • 用戶線程的很多操作對內(nèi)核來說都是透明的,不需要用戶態(tài)和內(nèi)核態(tài)的頻繁切換,使線程的創(chuàng)建、調(diào)度、同步等非常快;

缺點(diǎn):

  • 由于多個用戶線程對應(yīng)到同一個內(nèi)核線程,如果其中一個用戶線程阻塞,那么該其他用戶線程也無法執(zhí)行;

  • 內(nèi)核并不知道用戶態(tài)有哪些線程,無法像內(nèi)核線程一樣實現(xiàn)較完整的調(diào)度、優(yōu)先級等;

許多語言實現(xiàn)的協(xié)程庫基本上都屬于這種方式,比如python的gevent。

一對一模型

死磕 java線程系列之線程模型

一對一模型,又叫作內(nèi)核級線程模型,即一個用戶線程對應(yīng)一個內(nèi)核線程,內(nèi)核負(fù)責(zé)每個線程的調(diào)度,可以調(diào)度到其他處理器上面。

優(yōu)點(diǎn):

  • 實現(xiàn)簡單,本文由公從號“彤哥讀源碼”原創(chuàng);

缺點(diǎn):

  • 對用戶線程的大部分操作都會映射到內(nèi)核線程上,引起用戶態(tài)和內(nèi)核態(tài)的頻繁切換;

  • 內(nèi)核為每個線程都映射調(diào)度實體,如果系統(tǒng)出現(xiàn)大量線程,會對系統(tǒng)性能有影響;

Java使用的就是一對一線程模型,所以在Java中啟一個線程要謹(jǐn)慎。

多對多模型

死磕 java線程系列之線程模型

多對多模型,又叫作兩級線程模型,它是博采眾長之后的產(chǎn)物,充分吸收前兩種線程模型的優(yōu)點(diǎn)且盡量規(guī)避它們的缺點(diǎn)。

在此模型下,用戶線程與內(nèi)核線程是多對多(m : n,通常m>=n)的映射模型。

首先,區(qū)別于多對一模型,多對多模型中的一個進(jìn)程可以與多個內(nèi)核線程關(guān)聯(lián),于是進(jìn)程內(nèi)的多個用戶線程可以綁定不同的內(nèi)核線程,這點(diǎn)和一對一模型相似;

其次,又區(qū)別于一對一模型,它的進(jìn)程里的所有用戶線程并不與內(nèi)核線程一一綁定,而是可以動態(tài)綁定內(nèi)核線程, 當(dāng)某個內(nèi)核線程因為其綁定的用戶線程的阻塞操作被內(nèi)核調(diào)度讓出CPU時,其關(guān)聯(lián)的進(jìn)程中其余用戶線程可以重新與其他內(nèi)核線程綁定運(yùn)行。

所以,多對多模型既不是多對一模型那種完全靠自己調(diào)度的也不是一對一模型完全靠操作系統(tǒng)調(diào)度的,而是中間態(tài)(自身調(diào)度與系統(tǒng)調(diào)度協(xié)同工作),因為這種模型的高度復(fù)雜性,操作系統(tǒng)內(nèi)核開發(fā)者一般不會使用,所以更多時候是作為第三方庫的形式出現(xiàn)。

優(yōu)點(diǎn):

  • 兼具多對一模型的輕量;

  • 由于對應(yīng)了多個內(nèi)核線程,則一個用戶線程阻塞時,其他用戶線程仍然可以執(zhí)行;

  • 由于對應(yīng)了多個內(nèi)核線程,則可以實現(xiàn)較完整的調(diào)度、優(yōu)先級等;

缺點(diǎn):

  • 實現(xiàn)復(fù)雜,本文由公從號“彤哥讀源碼”原創(chuàng);

Go語言中的goroutine調(diào)度器就是采用的這種實現(xiàn)方案,在Go語言中一個進(jìn)程可以啟動成千上萬個goroutine,這也是其出道以來就自帶“高并發(fā)”光環(huán)的重要原因。

后面講到Java中的ForkJoinPool的時候,我們會拿Go語言的PMG線程模型來對比講解。

總結(jié)

(1)線程分為用戶線程和內(nèi)核線程;

(2)線程模型有多對一模型、一對一模型、多對多模型;

(3)操作系統(tǒng)一般只實現(xiàn)到一對一模型;

(4)Java使用的是一對一線程模型,所以它的一個線程對應(yīng)于一個內(nèi)核線程,調(diào)度完全交給操作系統(tǒng)來處理;

(5)Go語言使用的是多對多線程模型,這也是其高并發(fā)的原因,它的線程模型與Java中的ForkJoinPool非常類似;

(6)python的gevent使用的是多對一線程模型;

彩蛋

你所學(xué)過的語言都是使用的什么線程模型呢?

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI