天天看點

從線程與程序的差別這一問題出發

程序和線程基礎(理論概念)

1. 定義

看了下面的定義,可能會有點暈,但我還是要把他寫下來(為了嚴謹)。

程序是資源(CPU、記憶體等)配置設定的基本機關,具有一定獨立功能的程式關于某個資料集合上的一次運作活動,程序是系統進行資源配置設定和排程的一個獨立機關。

線程是程序的一個實體,是獨立運作和獨立排程的基本機關(CPU上真正運作的是線程)。線程自己基本上不擁有系統資源,隻擁有一點在運作中必不可少的資源(如程式計數器,一組寄存器和棧),但是它可與同屬一個程序的其他的線程共享程序所擁有的全部資源。

從線程與程式的差別這一問題出發

2.差別

線程基本上類似于程序(有時被稱為“輕量級程序”)。線程屬于程序。簡單的模型是在每個程序中有一個線程(在這種情況下,術語“線程”變得多餘),但任何程序都可以有多個線程。線程共享它們的大部分上下文,盡管它們每個都有一些私有資料空間,例如處理器寄存器和它們自己的堆棧。

  1. 程序是資源配置設定的基本機關;線程是程式執行的基本機關。
  2. 程序擁有自己的資源空間,沒啟動一個程序,系統就會為它配置設定位址空間;而線程與CPU資源配置設定無關,多個線程共享同一程序内的資源,使用相同的位址空間。
  3. 一個程序可以包含若幹個線程。

3. 優劣

正是因為這二者有差別,是以帶來的各自的優劣

  1. 線程之間的通信更友善,同一程序下的線程共享全局變量、靜态變量等資料,而程序之間的通信需要以通信的方式(Inter Process Communication,IPC)進行。不過如何處理好同步與互斥是編寫多線程程式的難點。
  2. 線程的排程與切換比程序快很多,同時建立一個線程的開銷也比程序要小很多。
  3. 但是多程序程式更健壯,多線程程式隻要有一個線程死掉,整個程序也死掉了,而一個程序死掉并不會對另外一個程序造成影響,因為程序有自己獨立的位址空間。
除此之外,推薦看一下阮一峰的一篇部落格:​​程序與線程的一個簡單解釋​​,用圖解釋十分生動形象。

為什麼這個問題是面試高頻?

既然這個問題是面試當中會被經常問到的,是以我去網上找一個答案,背出來不就好了。

但是,真的背答案就可以了嗎?

我們來分析一下為什麼衆多面試官老是問這個問題,他應該并不是想聽到一個對書本上概念的重複。

那麼,他究竟想考什麼?

  1. 側重點一:面試官想要了解面試者對這一知識點的了解程度(因為這是作業系統中不得不提的一個概念)。如果這個概念回答不上來,意味着面試者對作業系統的學習并不深。
  2. 側重點二:面試官可以對你的回答作進一步展開,通過你的回答某個側重點方向來進一步提問你對你自己回答的了解。(這個高頻問題的價值所在)。

比如:

  • 當你回答到:程序與線程的記憶體結構不同。程序與程序之間不能共享記憶體,而線程可以。那麼面試官就可以就記憶體這一點深入提問——記憶體如何尋址?
  • 當你回答:線程之間通信很友善,程序與程序通信不友善。那麼問題就又來了,你給我說一下程序之間怎麼通信?程序之間通信方法有哪些?不同通信方法有哪些優劣點?

再談“程序”與“線程”(口語表述)

程序的本質: :正在執行的一個程式,可以程序比作一個容器或者工廠

從線程與程式的差別這一問題出發

通過上圖,友善我們了解并記憶:

  1. 程序與程序之間相對獨立
  2. 程序可以包括幾個或者上百個線程在運作。
  3. 記憶體(邏輯記憶體)包括在程序裡面,每個程序的記憶體都是互相獨立的,但從一個更高的層次上看,不同的程序也共享着一個巨大的空間,這個空間就是整個計算機。
  4. 程序共有檔案/網絡句柄(handle),這樣可以打開同一個檔案,搶同一個網絡端口。

從不同的視角來看程序:

從線程與程式的差別這一問題出發

線程的本質:真正運作的是一個一個的線程

從線程與程式的差別這一問題出發

同理,上圖我們知道線程包含:

  1. 棧(堆棧):主線程的main函數、進行函數調用的參數和傳回位址、局部變量等内容都會被壓入棧内
  2. PC(Program Couner):程式計數器,PC的指針指向代碼所在的記憶體位址。
  3. TLS(Thread local storage):配置設定記憶體,存放變量

當有了上面的問題做引子後,面試官就可以借此引出更多話題:

1. 如何通信(溝通)的内容

通信是人的基本需求,程序與程序之間是互相獨立的,也有通信需求。根據這一問題就可以展開内容提問:

  • 程序/線程如何通信
  • 答:程序可以通過管道、套接字、信号互動、共享記憶體、消息隊列等等進行通信;而線程本身就會共享記憶體,指針指向同一個内容,互動很容易。
  • 通信方式的差異,比如程序間共享記憶體和消息隊列有何異同?

2. 如何同步(協調)的内容

一旦有了通信,人與人之間就會産生沖突,程序也一樣。這些沖突就會展現在如何同步上。

  • 在單個CPU下,實際上在任何時刻隻能有一個程序處于執行狀态。而其他程序則處于非執行狀态。我們是如何确定在任意時刻到底由哪個程序執行,哪些不執行呢?進而又可以引出鎖的概念?(如何進行程序排程?)
  • 線程之間的關系是合作關系。既然是合作,那就得有某種約定的規則,否則合作就會出問題。(如何進行線程同步?)

3. 關于記憶體原理相關問題

程序要配置設定記憶體,是以開銷很大,程序隻需要配置設定棧,配置設定一個PC就好,記憶體開銷小。

這一塊就可以問到了作業系統中的記憶體原理相關的内容。

線程可以由作業系統排程程式管理,或者在使用者級别由應用程式中的單獨排程程式管理。 (或兩者兼有!)在 Java(可能還有其他地方)中,在應用程式 (JVM) 中排程的線程稱為“綠色線程”;作業系統中的那些(如果可用)是“本機線程”。

就像程序一樣,每個線程都有自己的狀态:{正在運作、就緒或阻塞}。

從線程與程式的差別這一問題出發

使用者的線程管理通常允許更快的線程切換(不需要(慢)系統調用),并且可以根據應用程式定制排程,具有更可預測的行為。另一方面,這些可能需要使用依賴于所有線程“表現良好”的協作排程;例如,如果一個線程進行了阻塞的系統調用,則所有線程(在該程序中)都将被阻塞,即使其他線程(原則上)可以繼續;是以可能會有不必要的(且昂貴的)程序上下文切換。

作業系統的線程管理允許以與任何程序類似的方式排程線程。上下文切換(在同一程序内)可能比程序切換更便宜。

總結

總之,如果上述内容你都了解,那肯定是不怕被問到(大佬,請收下我的膝蓋);如果看了此篇文章之後,你能答出個大概,我相信面試官也會放過你,畢竟,我們也真的不是背書機器。是以,我們在回答過程中,盡量别給自己挖坑,用自己了解的知識點進行回答。切忌背書式的回答,模棱兩可,因為這樣面試官幾個連環炮就容易暴露問題了。

  • 程序是什麼?它指的是一個運動中的程式。從名字上看,程序表示的就是進展中的程式。一個程式一旦在計算機裡運作起來,它就成為一個程序。程序與程序之間可以通信、同步、競争,并在一定情況下可能形成死鎖。
  • 那麼線程是什麼?我們知道,程序是運轉的程式,是為了在CPU上實作多道程式設計而發明的一個概念。但是程序在一個時間隻能幹一件事情。如果想同時幹兩件事,辦法就是線程。線程是程序裡面的一個執行上下文或者執行序列。
  1. 《現代作業系統(第3版)》
  2. 《作業系統之哲學原理(第2版)》

繼續閱讀