這一次,真正明白程序與執行緒
引言
作為軟體工程師,程序與執行緒應該是我們必備的知識了,從年年各大企業的面試題就能看出來!
必考題:程序與執行緒的區別
小生本學期學習了作業系統這門課,最大的收穫就是學會了這道“必考題”。
最開始覺得自己學明白了,自己寫本文的時候,才覺得這裡牽扯到好多東西。
作業系統
什麼是作業系統?
說到作業系統,大家一定都不會陌生,我們用的手機內建了 Android
/ iOS
作業系統,我的開發用的電腦, Mac OS
、 Linux
、 Windows
等作業系統。
作業系統的非官方描述:作業系統是管理計算機硬體與軟體資源的系統軟體。
發展史
想真正明白程序與執行緒,我們需要了解一下計算機作業系統的歷史。
手工操作階段
最原始的時候,計算機沒有作業系統,只有單獨的機器,像下面這樣:
以一個現代人的眼光來看:沒有作業系統,這個機器怎麼用啊?反正給我一堆硬體,我是不能讓這些硬體跑起來。
前人們也是非常厲害的。他們使用記錄有程式和資料的卡片(前期用卡片,後來逐漸發展為使用打孔紙帶)去操作機器。
程式讀入機器後,機器就開始工作直到程式停止。據說圖靈能非常熟練地用這種方法操作 Manchester Mark I
機器。
缺點
CPU
批處理作業系統
為了解決人工操作速度遠慢於 CPU
的問題,引入了離線輸入/輸出系統。
計算機能夠自動地、成批地處理一個或多個使用者的作業,這就不需要手工輸入了,這就快了。
單道批處理作業系統
每次只加載一道作業到記憶體中執行。
多道批處理作業系統
每次載入多道作業到記憶體中併發執行,各個作業輪流使用處理機和其他系統資源,最終依次完成。
在記憶體中同時存放多道相互獨立的程式,這些程式共享系統資源,在作業系統的控制下交替在CPU上執行。
以後發展的作業系統,我們就不需要知道了,瞭解到這就足夠了。
程序與執行緒
程式併發執行
程式併發執行時,多道程式共享系統資源,此時,程式的執行失去了封閉性。
程式在併發執行時,是多個程式共享系統中的各種資源,因而這些資源的狀態將由多個程式來改變,致使程式的執行失去了封閉性。這樣,某程式在執行時,必然會受到其它程式的影響。
當多個程式併發執行時,我們期望的是執行變快,增加系統吞吐量。
但是,就如該圖一樣,某些程式必須在某些程式執行之後才可繼續執行,不能讓這個程式想執行就執行,我們要對其進行控制。
為了更方便地進行控制,我們就引入了程序的概念。
程序
在早期,程序是資源分配與排程的基本單位。
引入程序,我們發現解決了上述的問題,可以對 I1
、 I2
等等都建立程序,並按我們想法的前趨圖對程序執行進行約束,達到我們預期的效果。
然後程式對我們的進行進行排程,以達到併發執行的效果。
然後怎麼控制就是 PV
操作,訊號量,程序同步與互斥,這就不屬於本文的範圍了,大家可以自行學習。
程序不足
又過了好多年,人們發現最初的程序設計得有些缺點。
原始程序兩特點:
- 資源分配的基本單位。
- 排程的基本單位。
所以,在僅有程序的系統中,想實現併發,需要進行下列操作:
PCB PCB
還是這個圖為例,我需要建立 12
個程序,然後進行程序控制,讓它們併發執行。
建立程序 12
次,分配 12
次資源,分配資源消耗了大量的資源。
因為程序間的資源相互獨立,所以程序間切換是資源的切換,開銷相當大。
程式結束時,撤銷 12
次資源,回收資源時也有很大的開銷。
我們有沒有一種方法,可以減少建立、撤銷以及切換的開銷呢?
然後,引入了執行緒的概念。
執行緒
程序是攜帶資源的,切換時開銷太大,所以我們需要將資源分配與排程分開來。
在現代作業系統中,程序是資源分配的基本單位,執行緒是排程的基本單位。
一個程序中有多個執行緒,多個執行緒共享該程序的資源, CPU
直接排程程序。
還是這張圖,如果我們建立 1
個程序, 12
個執行緒會怎麼樣?
程式執行開始,建立一個程序,分配資源 1
次。
建立 12
個執行緒,注意,這裡是在程序內建立執行緒,所以,執行緒無需分配資源,直接使用其程序的資源即可,這開銷就非常少了。
12
個執行緒併發執行,這 12
個執行緒是共享一塊系統資源,所以線上程切換時,是不需要切換資源的,開銷大大減少。
撤銷時呢?撤銷執行緒 12
次,撤銷程序,回收資源 1
次。
總結
所以,這就是程序與執行緒的發展,瞭解了這些歷史,我想那些答案再也不用背了吧?
CPU
的一個核心只能執行一個執行緒,多個核心可以併發執行,但執行緒並行數最多不超過核心數。
4
核的,在不新增新技術的情況下,最多並行 4
個執行緒。
嗯? Core i7
不是 4
核 8
執行緒嗎?為什麼英特爾的 4
個核心能跑 8
個執行緒?
這就是英特爾大名鼎鼎的超執行緒技術,它將處理機核心中未利用的資源利用起來,再模擬出一個核心,雖然是 4
核心的處理機,所以在使用者看來,該 CPU
有 8
個邏輯核心。
在桌面端很有用,但是到了伺服器端,超執行緒技術會有些問題。這只是我看了很多篇關於伺服器端批判超執行緒的運維部落格之後的看法,待日後,我們再對該技術進行討論。