1. 程式人生 > >程序、執行緒、協程

程序、執行緒、協程

程序是執行著的應用程式,而執行緒是程序內部的一個執行序列。一個程序可以有多個執行緒。執行緒又叫做輕量級程序。

程序是讓作業系統的偽併發性成為可能

執行緒是讓程序裡面內部子任務的併發成為可能

最終目標是提高cpu的利用率

程序是系統分配的最小單元,執行緒是cpu排程的最小單元

1、程序是具有一定功能的程式關於某個資料集合上的一次執行活動,程序是系統進行資源排程和分配的一個獨立單位。

2、執行緒是程序的實體,是CPU排程和分派的基本單位,它是比程序更小的能獨立執行的基本單位。

3、一個程序可以有多個執行緒,多個執行緒也可以併發執行

程序的生命週期:建立-就緒-執行-等待-死亡

執行緒的生命週期:新建-就緒-執行-阻塞-等待-鎖池-死亡

兩者的對比:

1、排程方面:在引入執行緒的OS中,執行緒是獨立的排程和分派單位,而程序作為資源的擁有單位(相當於把未引入執行緒的傳統OS中的程序的兩個屬性分開了)。由於執行緒不擁有資源,因此可以顯著的提高併發度以及減少切換開銷。

2、併發性:引入了執行緒的OS中,程序間可以併發,而且一個程序內部的多個執行緒之間也是可以併發的,這就使OS具有更好的併發性,有效的提高了系統資源利用率和吞吐量。

3、擁有資源:無論OS是否支援執行緒,程序都是基本的資源擁有單位,執行緒只擁有很少的基本的資源,但是執行緒可以訪問所隸屬的程序的資源(程序的程式碼段,資料段和所擁有的系統資源如fd)

4、系統開銷:建立或者撤銷程序的時候,系統要為之建立或回收PCB,系統資源等,切換時也需要儲存和恢復CPU環境。而執行緒的切換隻需要儲存和恢復少量的暫存器,不涉及儲存器管理方面的工作,所以開銷較小。此外,統一程序中的多個執行緒由於共享地址空間,所以通訊同步等都比較方便。

如何理解一個程式可以對應多個程序,一個程序也可以對應多個程式?

    一個程式可以重複執行,開幾個視窗,比如網遊的“雙開”,一個程序可以對應多個程式就是一個DLL檔案可以被多個程式運用,比如DirectX9的動態連結庫,就是,許多遊戲都要有它才能執行。這就如同的車和路的關係,要去一個地方,可以有多條路,而一條路也可到達多個地方。

從其他方面詮釋:

    一開始大家想要同一時間執行那麼三五個程式,大家能一塊跑一跑。特別是UI什麼的,別一上計算量比較大的玩意就跟宕機一樣。於是就有了併發,從程式設計師的角度可以看成是多個獨立的邏輯流。內部可以是多cpu並行,也可以是單cpu時間分片,能快速的切換邏輯流,看起來像是大家一塊跑的就行。

  • 但是一塊跑就有問題了。我計算到一半,剛把多次方程解到最後一步,你突然插進來,我的中間狀態咋辦,我用來儲存的記憶體被你覆蓋了咋辦?所以跑在一個cpu裡面的併發都需要處理上下文切換的問題。程序就是這樣抽象出來的一個概念,搭配虛擬記憶體、程序表之類的東西,用來管理獨立的程式執行、切換。
  • 後來一個電腦上有了好幾個cpu,好咧,大家都別閒著,一人跑一個程序。就是所謂的並行
  • 因為程式的使用涉及大量的計算機資源配置,把這活隨意的交給使用者程式,非常容易讓整個系統分分鐘被搞跪,資源分配也很難做到相對的公平。所以核心的操作需要陷入核心(kernel),切換到作業系統,讓老大幫你來做。
  • 有的時候碰著I/O訪問,阻塞了後面所有的計算。空著也是空著,老大就直接把CPU切換到其他程序,讓人家先用著。當然除了I\O阻塞,還有時鐘阻塞等。一開始大家都這樣弄,後來發現不成,太慢了。為啥呀,一切換程序得反覆進入核心,置換掉一大堆狀態。程序數一高,大部分系統資源就被程序切換給吃掉了。後來搞出執行緒的概念,大致意思就是,這個地方阻塞了,但我還有其他地方的邏輯流可以計算,這些邏輯流是共享一個地址空間的,不用特別麻煩的切換頁表、重新整理TLB,只要把暫存器重新整理一遍就行,能比切換程序開銷少點。
  • 如果連時鐘阻塞、 執行緒切換這些功能我們都不需要了,自己在程序裡面寫一個邏輯流排程的東西。那麼我們即可以利用到併發優勢,又可以避免反覆系統呼叫,還有程序切換造成的開銷,分分鐘給你上幾千個邏輯流不費力。這就是使用者態執行緒
  • 從上面可以看到,實現一個使用者態執行緒有兩個必須要處理的問題:一是碰著阻塞式I\O會導致整個程序被掛起;二是由於缺乏時鐘阻塞,程序需要自己擁有排程執行緒的能力。如果一種實現使得每個執行緒需要自己通過呼叫某個方法,主動交出控制權。那麼我們就稱這種使用者態執行緒是協作式的,即是協程
  • 本質上協程就是使用者空間下的執行緒。

使用者執行緒與核心執行緒

    根據作業系統核心是否對執行緒可感知,可以把執行緒分為核心執行緒和使用者執行緒。

引入使用者執行緒,具體而言,有以下四個方面的優勢:

(1)可以在不支援執行緒的作業系統中實現。 (2)建立和銷燬執行緒、執行緒切換代價和執行緒管理的代價比核心執行緒少得多。 (3)允許每個程序定製自己的排程演算法,執行緒管理比較靈活。 (4)使用者執行緒能夠利用的表空間和堆疊空間比核心級執行緒多。

使用者執行緒的缺點主要有以下兩點: (1)同一程序中只能同時有一個執行緒在執行,如果有一個執行緒使用了系統呼叫而阻塞,那麼整個程序都會被掛起。 (2)頁面失效也會產生類似的問題。

參考連結: