操作系統如何實現多線程


  首先還是看多線程多進程在硬件上意味着什么,對於多CPU情況,多線程是如何進行調解的。復習下基本的概念

  進程:是操作系統(OS)[windows,Linux,Mac]進行資源(CPU、內存、磁盤、IO、帶寬等)分配的最小單位——>QQ,微信,網易雲等;

  線程:是CPU調度和分配的基本單位。一個進程可由多個線程的執行單元組成,每個線程都運行在同一進程的上下文中,共享同樣的代碼和全局數據。對於java來說,一個jvm進程至少有一個線程,也就是main方法所在的線程,我們把它叫做主線程,通過主線程可以創建更多線程。此外,線程又分為用戶線程和守護線程。兩者區別在於,守護線程會隨着主線程結束而結束。

  進程=容器,包含了該進程的所有線程。線程共享進程擁有的資源,例如00000000ff~00000ff之間的邏輯內存地址。

  進程是程序的一次執行過程,是對CPU的抽象,是正在運行的程序的抽象。操作系統通過調度將CPU的控制權交給某個進程。

  進程控制塊(PCB)是操作系統用於管理控制進程的一個專門的數據結構,記錄進程的各種屬性

  PCB是系統感知進程存在的唯一標志,進程與PCB是一一對應的,PCB包含的信息:

  • 進程描述信息:進程標識符PID,唯一,整數,進程名(不唯一),用戶標識符userID,進程組關系(兄弟父子關系)
  • 進程控制信息:當前狀態,優先級,代碼執行入口,運行統計信息,進程間同步和通信,進程隊列指針,進程消息隊列指針
  • 所擁有的資源和使用情況:虛擬地址空間的狀況,打開文件列表
  • CPU現場信息:進程不運行時的寄存器值和指向該進程的頁表的指針

 進程有以下狀態模型:

  在硬件架構中還有一個進程隊列,用來存放進程。操作系統會給一類進程安裝一個或者多個隊列。隊列元素為PCB,伴隨進程狀態的改變,其PCB從一個隊列進入另一個隊列,然后再進行出入的操作。

 

  至於JVM和操作系統的關系是如上圖所示的,而操作系統其實也是一個程序,JVM是建立在操作系統之上的程序。

  jvm的設計的模型其實就是操作系統的模型,基於操作系統的角度,jvm也就是一個應用(java.exe/javaw.exe),而基於class文件來說,jvm就是個操作系統,而jvm的方法區,也就相當於操作系統的硬盤區,所以方法區也被叫做permanent區,因為這個單詞是永久的意思,也就是永久區。而java棧和操作系統棧是一致的,無論是生長方向還是管理的方式,至於堆嘛,雖然概念上一致目標也一致,分配內存的方式也一直(new,或者malloc等等),但是由於他們的管理方式不同,jvm是gc回收,而操作系統是程序員手動釋放,所以在算法上有很多的差異。一般我們通過 java xxx 執行 java 程序就會運行一個 jvm 實例,對操作系統而言,它就是一個普通的進程。進程和操作系統交互就是通過系統調用了,不過一般都是通過各種庫(比如 linux 的 glibc)間接使用系統調用。

  進程是一個程序的單次執行,如果一個程序持續占有CPU,就會從CPU開啟到結束持續性的占用CPU。於是出現了操作系統調度器,而進程也成為了調度單位.在這里就出現了並發的概念,調度器切換,CPU給不同進程使用的速度非常快。

  線程是進程的衍生,一個進程可以擁有多個線程,可以理解為線程拆分開了進程。例如讀線程,寫線程。

  如果計算機有多個cpu核,且計算機中的總的線程數量小於核數,那線程就可以並行運行在不同的核中,如果是單核多線程,那多線程之間就不是並行,而是並發,即為了均衡負載,cpu調度器會不斷的在單核上切換不同的線程執行,但是我們說過,一個核只能運行一個線程,所以並發雖然讓我們看起來不同線程之間的任務是並行執行的,但是實際上卻由於增加了線程切換的開銷使得代價更大了。如果是多核多線程,且線程數量大於核數,其中有些線程就會不斷切換,並發執行,但實際上最大的並行數量還是當前這個進程中的核的數量,所以盲目增加線程數不僅不會讓你的程序更快,反而會給你的程序增加額外的開銷。

  實現並行計算有三種方式,多線程,多進程,多進程+多線程。如果是多進程,因為每個進程資源是獨立的(地址空間和數據空間),就要在操作系統層面進行通信,如管道,隊列,信號等;多線程的話會共享進程中的地址空間和數據空間,一個線程的數據可以直接提供給其他線程使用,但方便的同時會造成變量值的混亂,所以要通過線程鎖來限制線程的執行

  並行只存在於多個CPU的情況下,單CPU只能做到並發。對於CPU而言, CPU 看到的是線程,看不到進程,進程是 OS 上的概念。

  CPU只能做一個事情就是執行command,給什么做什么。

  那么有沒有可能2個CPU執行一個進程中不同線程呢?邏輯上我覺得是可行的,主存只有一個,CPU只是執行的工具,如果一個進程的不同線程不存在互相依賴的情況那么就肯定可以進行這種情況的執行。

 
  多核才有真正的多線程,單核條件下只能是各種調度算法下的偽並行,實際上同一時刻還是只有一個線程在運行。

  CPU在一個時間點只能做一件事,因為切換的速度快所以看起來好像是同時執行多個線程而已。

  實際上就是用定時器來做時基,以時間片的方式分別執行來實現的,只不過實現起來細節比較復雜,核心思想就是你猜想的那樣。划分一塊內存區域做線程的上下文切換空間,另外以一個定時器做定時時基。例如設為1ms,每隔1ms檢測是否有其它線程要工作,如果有,保存當前線程的CPU寄存器以及工作狀態到當前線程的上下文空間,從要運行的線程上下文空間取出寄存器值填充到CPU寄存器中,這樣就完成了線程的切換,CPU就接着另一個線程的工作繼續做下去了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM