1. 程式人生 > >程序與執行緒(一)——程序

程序與執行緒(一)——程序

序言:


我們知道多執行緒是現代作業系統中一個很重要的組成部分。它經常在面試過程中或者在實際運用過程中都會碰到的一個比較難的一個問題,所以這篇文章所屬的一個系列,將淺顯的記錄下博主的多執行緒學習的一個過程。

首先呢,說起執行緒的起源,我們不得不提就是程序的概念。然而一開始也並不是直接就有的程序的,而是由多道處理程式環境下,演化而來的。
由於多道程式有間斷性和失去封閉性、以及不可再現性,催生出了程序的產生。淺顯的來說,程序就可以能使程式併發的執行程式,並加以描述和控制。這又是為什麼呢?因為其中有一個專門的資料結構稱為程序控制塊。那麼什麼是程序?又是程序控制塊呢?什麼又是執行緒呢?如何處理多執行緒呢?我們接著看下去。


一. 為什麼要引入程序


這個部分可以分兩個部分來看:


1.在20世紀60年代中期,IBM開發了OS/360作業系統是第一個多道程式的批處理系統,在引入程式間的併發執行功能後,雖然提高了系統的吞吐量和資源的利用率,但同時也帶來了一系列的問題:(1)間斷性。程式在併發執行時,由於它們共享系統資源,它們之間必將會形成互相制約的關係。(2)失去封閉性。當系統中存在著多個以可以併發執行的程式時,系統中的各種資源將為他們所使用。這就意味著其中一個程式在執行時。其環境都必然會受到其他程式的影響。這不同於我們現在對作業系統已有的觀念,其實這有點兒像多執行緒中對共享變數不加鎖的情況。(3)不可再現性。一段程式的執行出現了多種可能,而且出現了不確定性。我們知道程式的確定性是一個基本的要素。

2.我們進一步來看待這一個問題。在第一點中我們提到了資源利用率和系統吞吐量的問題,並且間斷性的原因在於它們之間互相制約。這又是為什麼呢?這是因為我們計算機的儲存層次結構之間訪問速率不匹配的原因造成的。CPU的速度比記憶體快,記憶體比硬碟快,硬碟又比讀取網路資源快。為解決這個問題,作業系統就由此誕生了。一旦開機後,作業系統進入記憶體,它就是老大了。對我們計算機一個全域性的掌控。它自帶各種演算法,其目的是尋找到一箇中庸之道,讓我們的計算機得以平衡和穩定地執行。程序就是在作業系統演化過程中產生的。程序也服從作業系統一系列規則執行。




二.程序的定義


首先,程序可以簡單的定義為一個正在執行中的程式。舉個例子:JVM是一個程序,QQ是一個程序,瀏覽器是一個程序等等。我們可以開啟工作管理員可以看到,我們的電腦執行著很多很多的程序。





同時我們又可以看到CPU的利用率是忽高忽低的,這是為什麼呢?




肯定不是因為抽風,而是因為在作業系統的管理下,由程序排程演算法,不斷地有程序在記憶體中換進換出,程序的執行是要佔有CPU的,一個CPU同一時刻只能執行一個程序中的某一指令,程序有時候佔用CPU多,有時候佔用CPU少。不同的程序,所需要的CPU等資源也就是不一樣的。所以就出現了這樣一個現象。不光如此,程序執行的同時,也要消耗計算機的各種資源:CPU、記憶體、網路、IO、檔案系統

所以這說明了兩點:程序是擁有資源的獨立單位。程序同時又是一個可獨立和分派的基本單位。

    然後,我們再具體說明程序的概念:一個具有獨立功能的程式在一個數據集合上的一次動態執行的過程。

這裡要注意程序和程式的區別。一個是動態的,一個是靜態的。一個靜態的程式靜靜的躺在硬碟上(java編譯後的.class檔案便是如此),通過作業系統分給它一個程序控制塊,在記憶體中讓CPU執行起來,這個執行過程,稱為程序。它是一個動態的過程。


三. 程序的組成


程式的程式碼 
程式處理的資料 
要知道現在執行哪條指令,程式計數器PC中的值指示將執行的指令。 
CPU暫存器會動態變化,一組通用暫存器的當前值,堆,棧等; 
各種系統資源,記憶體,外存,網路。

包含了正在執行的一個程式的所有狀態資訊,這些資訊基本都記錄在程序控制塊PCB(Process Control Block)中:


四. 程序的特點


(a)併發性: 併發:在一段時間內有多個程序在執行。如果這個時間很小,給人一種感覺是多個程序在一起執行一樣 並行:在一個時刻有多個程序在執行。一個CPU在同一時刻沒有辦法執行多個程式,只能執行一個程式,沒有辦法並行。 併發和並行時間的粒度是不一樣的。 (b)動態性:很好理解,程序的實質是程式的執行過程。程序有一定的生命週期:它由建立而產生,由排程而執行,由撤銷而消亡。 (c)獨立性:從兩個方面來看,正確性,其他程序不會破壞到我們程序不會破會我們程式碼,不會破壞我們的資料 ——記憶體管理中頁表的功能——使不同的程式訪問不同的地址空間, 不可能越過地址空間,越過會產生缺頁異常,頁錯誤。 (d)制約性:與其他程式的互動和制約,同步互斥
五 程序控制塊(重要)————程序的唯一標誌。和我們的身份證號一樣重要,裡面有一個程序標識PID,同樣在工作管理員中也可以看到:


程序和程序控制塊是一對一的關係,程序建立,程序控制塊建立,程序消失,程序控制塊消失。 程序控制塊PCB有三大類資訊: (一)程序標識資訊一個PCB唯一標識了一個程序,程序ID識別出來到底代表著哪一個程式在執行,或者說一個程式執行了幾次,都可以通過程序控制塊的程序標識來體現。還有標識這個程序是屬於哪一個使用者的,這個程序的父程序(建立這個程序的程序)。 (二)處理機狀態資訊——主要是暫存器。 CPU在執行過程中會使用CPU做很多的事情,比如說,加減乘除計算儲存、儲存的狀態資訊(是否溢位)、執行過程(執行到什麼地方了,棧在什麼地方,堆在什麼地方)、程式計數器暫存器 、棧指標暫存器。 使用者可見暫存器,程式使用的資料,地址 控制和狀態暫存器,程式計數器pc,程式狀態字PSW 棧指標,過程呼叫/系統呼叫/中斷處理和返回時需要用到 (三) 程序控制資訊 作業系統對程序的管理和控制:讓它處於執行的狀態還是等待、就緒。程序臨時的執行的特徵。 程序間的通訊 記憶體資訊:程式碼 程序控制塊的連線資訊:PCB控制塊,父子程序之間的關係,管理資訊
六 程序的狀態(重要)
程序建立:建立並不是立即執行的,而是進入一個就緒狀態,等待排程算法佔據CPU執行

程序執行:核心選擇一個就緒的程序,讓它佔用處理機(cpu)並執行 

程序等待(阻塞):三種情況:(1)請求並等待系統服務,無法馬上完成;

(2)某種操作(和其他程序協調工作),無法馬上完成;(3)需要的資料沒有到達 

程序自己觸發阻塞,因為只有自己才知道何時需要等待某事件 。程序只能自己阻塞自己。


程序喚醒:需要的資源可被滿足,等待的事件到達,都意味著可將該程序的PCB插入到就緒佇列 。注意,被喚醒後不能立即執行,需要進入到就緒狀態,等待佔有CPU。因為自身沒有佔用cpu執行,所以只能被OS或其他程序喚醒 


程序結束:結束情況:自願(正常退出,錯誤退出),強制性的(致命錯誤,被其他程序所殺)

綜上我們稱之為五狀態圖:



其中多了一條執行到就緒狀態,因為該程序時間片用完了,就緒對列有很多需要處理,所以CPU只分配一點點時間給每一個程序。作業系統讓它退出了CPU,等待再次被排程。同時作業系統根據執行緒優先順序加之排程演算法排程其他執行緒。首先是作業系統排程器完成排程。作業系統時鐘在起作用:知道執行了多久,一旦超時,作業系統就會得到感知,執行態的程序就會停下來,變成就緒態,再選擇一個就緒太的程序佔用CPU來執行。

PS:關於排程演算法又是一門學問了,我們之後再講,先佔坑。



接著我們有七狀態圖:引入程序掛起,和程序啟用。


程序掛起和程序阻塞是不太一樣的。以及為什麼要程序掛起? 程序掛起:程序沒有佔有記憶體空間。——和記憶體管理有緊密的聯絡。在虛擬記憶體管理的時候,執行的程式有可能是它把它一部分空間會導到硬碟上去,騰出更多的空間給後面需要的程式使用。 現在執行的程式就是程序,程序如果沒有佔有記憶體空間,也就意味著程序被切換到了(swapout)到硬碟上去了,這時候就沒有佔有記憶體空間了,這時候就稱為程序掛起。 掛起分兩類:阻塞掛起和就緒掛起。 阻塞掛起:程序在磁碟上等待某個事件的出現,第一,已落在磁碟上去了,第二,它還在等待某個事件的出現 就緒掛起:程序本身處於就緒狀態。這時候它的地址空間的內容 也是在硬碟上,這時候下面被換如到記憶體之後,它本身就處於就緒態。 一個是程序本身處於阻塞的狀態被掛起,還一個是程序屬於就緒的狀態時被掛起。
阻塞到阻塞掛起:記憶體不夠用了,會把阻塞的一些程序變到阻塞掛起,這時候阻塞程序所佔用的記憶體空間就會騰出來給其他的就緒態,和正在執行的程序所使用。 就緒到就緒掛起:一般來說,就緒的程序會比阻塞的程序優先順序要高一些。作業系統就會優先選擇處於阻塞狀態的程序變到阻塞掛起狀態,把它的記憶體給釋放出來
阻塞掛起到就緒掛起:當處於阻塞掛起的程序,事件得到滿足時,這個時候,程序會變成就緒態,但是需要注意,這個程序本身就是還在掛起在硬碟上,這個時候我們只是把阻塞掛起到就緒掛起,但是程序本身的所有的資源,所有的記憶體的資料都還在硬碟上,我們只是把它的狀態變了。