操作系统中的进程与线程和java中的线程
簡介
??? 在傳統的操作系統中,進程擁有獨立的內存地址空間和一個用于控制的線程。但是,現在的情況更多的情況下要求在同一地址空間下擁有多個線程并發執行。因此線程被引入操作系統。
為什么需要線程?
??? 如果非要說是為什么需要線程,還不如說為什么需要進程中還有其它進程。這些進程中包含的其它迷你進程就是線程。
??? 線程之所以說是迷你進程,是因為線程和進程有很多相似之處,比如線程和進程的狀態都有運行,就緒,阻塞狀態。這幾種狀態理解起來非常簡單,當進程所需的資源沒有到位時會是阻塞狀態,當進程所需的資源到位時但CPU沒有到位時是就緒狀態,當進程既有所需的資源,又有CPU時,就為運行狀態。
??? 線程的好處如下:
??? 1.在很多程序中,需要多個線程互相同步或互斥的并行完成工作,而將這些工作分解到不同的線程中去無疑簡化了編程模型。
??? 2.因為線程相比進程來說,更加的輕量,所以線程的創建和銷毀的代價變得更小。
??? 3.線程提高了性能,雖然線程宏觀上是并行的,但微觀上卻是串行。從CPU角度線程并無法提升性能,但如果某些線程涉及到等待資源(比如IO,等待輸入)時,多線程允許進程中的其它線程繼續執行而不是整個進程被阻塞,因此提高了CPU的利用率,從這個角度會提升性能。
??? 4.在多CPU或多核的情況下,使用線程不僅僅在宏觀上并行,在微觀上也是并行的。
經典線程模型
?另一個看進程和線程的角度是進程模型基于兩類不同的概念:資源的組織和執行。在過去沒有線程的操作系統中,資源的組織和執行都是由進程完成的。但區分這兩者很多時候需要加以區分,這也是為什么需要引入線程。
??? 進程是用于組織資源的單位,進程將相關的資源組織在一起,這些資源包括:內存地址空間,程序,數據等,將這些以進程的形式組織起來可以使得操作系統管理這些資源更為容易。
??? 而線程,是每一個進程中執行的一個條線。線程雖然共享進程中的大多數資源,但線程也需要自己的一些資源,比如:用于標識下一條執行指令的程序計數器,一些容納局部變量的寄存器,以及用于表示執行的歷史的棧。
??? 總而言之:進程是組織資源的最小單位,而線程是安排CPU執行的最小單位。
??? 其實在一個進程中多個線程并行和在操作系統中多個進程并行非常類似,只是線程共享的是地址空間,而進程共享的是物理內存,打印機,鍵盤等資源……
每一個進程和線程所獨自占有的資源如表1所示。
| 進程占有的資源 | 線程占有的資源 |
| 地址空間?? 全局變量?? 打開的文件?? 子進程?? 信號量?? 賬戶信息 | 棧?? 寄存器?? 狀態?? 程序計數器 |
表1.進程和線程所獨占的資源其中,線程可以共享進程獨占的資源。
?? 在多線程的進程中,每個線程輪流使用CPU,因此實際上線程并不是并行的,但從宏觀上看,是并行的。
??? 在多線程模型中,每一個進程初始創建時只有一個線程。這個線程可以通過調用系統的庫函數去創建其它線程。線程創建的線程并必須要為其指定地址,因為新的線程自動在創建它的地址空間內工作。雖然一個線程可以創建另一個線程,但通常來講,線程之間是并列的,并不存在層級關系。
??? 當一個進程完成其工作后,可以通過調用系統庫函數進行銷毀。
操作系統實現線程的幾種模式
???? 在操作系統中,線程可以實現在用戶模式下,也可以實現在內核模式下,也可以兩者結合實現。
線程實現在用戶空間下
?當線程在用戶空間下實現時,操作系統對線程的存在一無所知,操作系統只能看到進程,而不能看到線程。所有的線程都是在用戶空間實現。在操作系統看來,每一個進程只有一個線程。過去的操作系統大部分是這種實現方式,這種方式的好處之一就是即使操作系統不支持線程,也可以通過庫函數來支持線程。
??? 在這種模式下,每一個進程中都維護著一個線程表來追蹤本進程中的線程,這個表中包含表1中每個線程獨占的資源,比如棧,寄存器,狀態等。
? 這種模式當一個線程完成了其工作或等待需要被阻塞時,其調用系統過程阻塞自身,然后將CPU交由其它線程。
??? 這種的模式的好處,首先,是在用戶空間下進行進程切換的速度要遠快于在操作系統內核中實現。其次,在用戶空間下實現線程使得程序員可以實現自己的線程調度算法。比如進程可以實現垃圾回收器來回收線程。還有,當線程數量過多時,由于在用戶空間維護線程表,不會占用大量的操作系統空間。
??? 有好處就有壞處,這種模式最致命的缺點也是由于操作系統不知道線程的存在,因此當一個進程中的某一個線程進行系統調用時,比如缺頁中斷而導致線程阻塞,此時操作系統會阻塞整個進程,即使這個進程中其它線程還在工作。還有一個問題是假如進程中一個線程長時間不釋放CPU,因為用戶空間并沒有時鐘中斷機制,會導致此進程中的其它線程得不到CPU而持續等待。
?
線程實現在操作系統內核中
?在這種模式下,操作系統知道線程的存在。此時線程表存在操作系統內核中;
? 在這種模式下,所有可能阻塞線程的調用都以系統調用(System Call)的方式實現,相比在用戶空間下實現線程造成阻塞的運行時調用(System runtime call)成本會高出很多。當一個線程阻塞時,操作系統可以選擇將CPU交給同一進程中的其它線程,或是其它進程中的線程,而在用戶空間下實現線程時,調度只能在本進程中執行,直到操作系統剝奪了當前進程的CPU。
??? 因為在內核模式下實現進程的成本更高,一個比較好的做法是另線程回收利用,當一個線程需要被銷毀時,僅僅是修改標記位,而不是直接銷毀其內容,當一個新的線程需要被創建時,也同樣修改被“銷毀”的線程其標記位即可。
??? 這種模式下同樣還是有一些弊端,比如接收系統信號的單位是進程,而不是線程,那么由進程中的哪一個線程接收系統信號呢?如果使用了表來記錄,那么多個線程注冊則通過哪一個線程處理系統信號?
混合模式
??? 還有一種實現方式是將上面兩種模式進行混合,用戶空間中進程管理自己的線程,操作系統內核中有一部分內核級別的線程,如圖5所示???? 在這種模式下,操作系統只能看到內核線程。用戶空間線程基于操作系統線程運行。因此,程序員可以決定使用多少用戶空間線程以及操作系統線程,這無疑具有更大的靈活性。而用戶空間線程的調度和前面所說的在用戶空間下執行實現線程是一樣的,同樣可以自定義實現。
在這種混合實現下,即存在用戶線程,也存在輕量級進程。用戶線程還是完全建立在用戶空間中,因此用戶線程的創建、切換、析構等操作依然廉價,并且可以支持大規模的用戶線程并發。而操作系統提供支持的輕量級進程則作為用戶線程和內核線程之間的橋梁,這樣可以使用內核提供的線程調度功能及處理器映射,并且用戶線程的系統調用要通過輕量級進程來完成,大大降低了整個進程被完全阻塞的風險。在這種混合模式中,用戶線程與輕量級進程的數量比是不定的,即為N:M的關系:
目前來說,作為異步回調以外的另一種解決方案,這種m:n的線程模型可以說大有可為,Golang的協程就是使用了這種模型,在用戶態,協程能快速的切換,避免了線程調度的CPU開銷問題,協程相當于線程的線程。
協程
?
類似與線程于進程而言,后面人們又泛化出協程
進程,線程,協程的主要目的是提高效率。而線程和進程是搶占式的程序,在什么時間哪個線程或進程使用cpu是操作系統決定的。操作系統層面我們是無法控制的。而協程是用戶可以調度誰先誰后的。yield是協程的一個最底層的實現。
cpu雖然可以分時操作,但是能開啟的進程是有限的,盡管線程比較輕量,一個cpu同一時刻只能處理一個線程。如果我要處理的任務是無限,如50000個,假如開了200個線程,這200個線程都阻塞了,那下面的4萬多個都動不了。當然,如果一個ie線程中沒有IO阻塞,只有計算,cpu就會得到充分利用。但是實際情況中往往IO阻塞非常多,如果阻塞程序就停止,就不能做其他事情了,雖然操作系統會調度其他進程或線程工作,但是當前的進程還是會有分配給他的時間片,而他實際是阻塞時還占用著cpu,這是對cpu的浪費。
而進程,線程都會占用系統資源,在他們之間切換也會浪費一些時間,所以在高并發越來越重要的今天,使用線程或進程就不能滿足我們了。
所以有了協程:也叫纖程,對于cpu來說,線程是他執行的最小單位,也就是說他只能看到線程,協程是看不到的。
一條線程 在多個任務之間來回切換,切換這個動作是浪費時間的。對于cpu,操作系統來說,協程是不存在的,他們只管執行線程。他們不管你執行哪個任務,只管執行線程的指令。
纖程(Fiber)
和協程是一個東西,只不過在windows下叫纖程。
有一些參考資料:https://blog.csdn.net/BIackMamba/article/details/92983852?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
2、https://www.cnblogs.com/CareySon/archive/2012/05/04/ProcessAndThread.html
3、https://blog.csdn.net/CringKong/article/details/79994511
4、https://www.jianshu.com/p/dd4a480a1410
?
?
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的操作系统中的进程与线程和java中的线程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux Swap空间利用率过高
- 下一篇: mysql百万级性能瓶颈-数据库选型