一.概述
這裡以Linux為例。Linux歷史上,最開始使用的線程是LinuxThreads,但LinuxThreads有些方面受限於內核的特性,從而違背了SUSV3 Pthreads標准。即它要根據內核的特性來實現線程,有些地方沒有遵循統一的標准。後來IBM開發了NGPT(Next Generation POSIX Threads),性能明顯優於LinuxThreads,人們曾把它當作LinuxThreads的繼任者。但最後,又有一個項目NPTL(Native POSIX Threads Library)出來後,性能更優於NGPT。2002年NGPT項目停止開發,我們現在用的Linux線程就是NPTL。
線程的實現曾有3種模型:
1.多對一(M:1)的用戶級線程模型
2.一對一(1:1)的內核級線程模型
3.多對多(M:N)的兩級線程模型
上面的x對y(x:y)即x個用戶線程對應y個內核調度實體(Kernel Scheduling Entity,這個是內核分配CPU的對象單位)。
LinuxThreads和NPTL都是采用一對一的線程模型,NGPT采用的是多對多的線程模型!!!
二.多對一用戶線級程模型
多對一線程模型中,線程的創建、調度、同步的所有細節全部由進程的用戶空間線程庫來處理。用戶態線程的很多操作對內核來說都是透明的,因為不需要內核來接管,這意味不需要內核態和用戶態頻繁切換。線程的創建、調度、同步處理速度非常快。當然線程的一些其他操作還是要經過內核,如IO讀寫。這樣導致了一個問題:當多線程並發執行時,如果其中一個線程執行IO操作時,內核接管這個操作,如果IO阻塞,用戶態的其他線程都會被阻塞,因為這些線程都對應同一個內核調度實體。在多處理器機器上,內核不知道用戶態有這些線程,無法把它們調度到其他處理器,也無法通過優先級來調度。這對線程的使用是沒有意義的!
三.一對一內核極線程模型
一對一模型中,每個用戶線程都對應各自的內核調度實體。內核會對每個線程進行調度,可以調度到其他處理器上面。當然由內核來調度的結果就是:線程的每次操作會在用戶態和內核態切換。另外,內核為每個線程都映射調度實體,如果系統出現大量線程,會對系統性能有影響。但該模型的實用性還是高於多對一的線程模型。
四.多對多兩極線程模型
多對多模型中,結合了1:1和M:1的優點,避免了它們的缺點。每個線程可以擁有多個調度實體,也可以多個線程對應一個調度實體。聽起來好像非常完美,但線程的調度需要由內核態和用戶態一起來實現。可想而知,多個對象操作一個東西時,肯定要一些其他的同步機制。用戶態和內核態的分工合作導致實現該模型非常復雜。NPTL曾經也想使用該模型,但它太復雜,要對內核進行大范圍改動,所以還是采用了一對一的模型!!!