使用者態多執行緒實現的基本原理

2021-08-24 22:09:43 字數 1426 閱讀 5989

本文參考了使用者態非搶占式執行緒庫實現 一文以及gnu pth 。前者是一種使用者態執行緒庫的簡單實現,屬於乙個很好的demo,後者就是大家熟知的pthread的使用者態實現,比較完善。

keywords: user-space multithreading, pth

所謂多執行緒,簡單講就是能夠讓幾個不同的**片段輪流執行。核心實現多執行緒的方法比較直觀,在每次時鐘中斷到來時或者使用者呼叫syscall陷入核心時進行上下文切換即可。使用者態切換執行緒要解決兩個問題:

1、時機,即何時切換執行緒?

2、方法,即怎樣切換上下文?

為了決定切換時機,需要確定所設計的執行緒庫是可剝奪(preemptive)的還是不可剝奪(non-preemptive)的。一般,使用者態執行緒庫都選擇使用不可剝奪的設計方案,這麼做的好處是將控制權交給使用者,而使用者最了解何時需要放棄執行權。這麼做減少了系統切換次數,實現了最高的cpu利用率,非常適合用於科學計算環境。但是,另一方面這麼做也存在缺點:其它執行緒的響應速度變慢,他們必須等到當前cpu放棄執行權後才能被執行。能不能將使用者執行緒設計成可剝奪的呢?這應該也是可行的。每個使用者執行緒執行一段時間後會被迫暫停執行,被動地將控制權交回給排程器。怎樣才能「被迫暫停執行」?這是方法問題,下面就要講到。

對於不可剝奪方式,需要使用者編寫程式的時候主動呼叫諸如thread_yeild(), thread_wai()之類的函式,這些函式會將當前使用者執行緒的執行上下文儲存起來,然後讓排程器選擇乙個新的使用者執行緒投入執行。底層作業系統提供了一些列的機制支援上下文的獲得和切換,如setjmp,longjmp,getcontext,swapcontext等。使用者態非搶占式執行緒庫實現 一文使用了前面兩個函式,gnu pth 使用了後面兩個函式。可剝奪方式的實現需要更多的作業系統支援,如可以利用alarm函式周期性地產生使用者態中斷,每次中斷到來的時候執行緒庫進行執行緒切換。

單純的使用者態執行緒庫一般都是基於乙個單執行緒程序實現的,一旦使用者執行緒阻塞,這個程序就被阻塞,進而導致整個使用者態執行緒組得不到cpu。基於單程序實現的使用者態執行緒庫在smp/多cpu環境下效能很差,多出來的核無法被執行緒庫利用,這跟當前的微處理器架構發展趨勢十分不符。為了解決這個問題,可以考慮使用一種混合結構:在少量核心執行緒的基礎上實現大量的使用者執行緒。

最後思考乙個問題:為什麼使用者態執行緒庫比核心態執行緒庫具有更高的效能呢?其實使用者態執行緒庫同樣離不開進入核心態這一過程,以getcontext,swapcontex實現方式為例,getcontext要進出一次核心,swapcontex又要進出一次核心,而核心執行緒切換則只需要一次時鐘中斷,只進出核心一次即可。這麼說來,使用者態執行緒庫的效能應該劣於核心態執行緒庫。但是,注意到每次時鐘中斷所做的工作遠遠不止上下文切換這麼簡單,這應該是使用者態執行緒庫更優的原因吧。基於這個分析,如果應用需要建立的執行緒數並不多,二者應該效能相當。但是,一旦執行緒數巨大且切換頻繁,使用者態執行緒庫的優勢就能體現出來了。

執行緒基本原理

1 每個執行緒都會建立自己的棧空間,執行自己的run方法。2 執行緒同步 執行緒安全問題都是由全域性變數及靜態變數引起的。若每個執行緒對全域性變數 靜態變數只有讀操作,而無寫操作,那麼這個全域性變數是執行緒安全的。若多個執行緒同時執行寫操作,一般需要考慮執行緒同步,否則影響執行緒安全。資料同步的三個...

mysql的基本原理 Mysql 基本原理

mysql 基本原理 mysql是一種關聯式資料庫管理系統,關聯式資料庫將資料儲存在不同的表中,而不是將所有資料放在乙個大倉庫內,這樣就增加了速度並提高了靈活性 ysql是資料庫登入命令 uroot預設超級使用者登入 p 預設沒密碼 中寫密碼 mysqladmin uroot password 12...

多執行緒 JUC學習 執行緒池 執行緒池基本原理

如果併發的執行緒數量很多,並且每個執行緒都是執行乙個時間很短的任務就結束了,這樣頻繁建立執行緒就會大大降低系統的效率,因為頻繁建立執行緒和銷毀執行緒需要時間。執行緒池使得執行緒可以復用,就是執行完乙個任務,並不被銷毀,而是可以繼續執行其他的任務。降低資源消耗。重複利用已建立執行緒,降低執行緒建立與銷...