線程概念簡介 什麼是線程 多線程上篇(七)

  操做系統爲了程序的併發執行引入了進程的概念,提升了資源的利用率以及吞吐量。
在20世紀 60年代人們提出了進程的概念後,在OS中一直都是以進程做爲能擁有資源和獨立運行的基本單位的。
直到 20 世紀 80 年代中期,人們又提出了比進程更小的能獨立運行的基本單位——線程(Threads)
試圖用它來提升系統內程序併發執行的程度,從而可進一步提升系統的吞吐量。
簡言之,進程的概念,使之可以併發執行多道程序,線程的概念讓你更好地併發執行程序,一個是能不能的問題,一個是更好的問題。

線程與進程對比

線程概念的發展

image_5c5bab07_4fdf
進程概念提出的目的就是爲了多道程序併發執行,併發過程當中必然意味着不斷地進程調度任務切換,可是他又是資源分配的獨立單位,也就是說他要揹着資源來回跑。
舉個例子:
辦公室內,每一個人都有一臺電腦,電腦就是資源
而後你們常常須要不斷地變換座位位置(好比你們都是哪裏須要去哪裏,客服缺人了,銷售就頂一個過去)
每一個人都抱着本身的電腦來回的換位置方便?仍是你們只是人員走動,電腦就使用那個位置的電腦方便?
進程也是有些相似的道理你帶着這麼多資源來回切換調度,必然會帶來更多的時&&空開銷
因此建立了線程的概念程序運行時所需的資源和程序的調度進行解耦
進程仍舊負責資源的獨立分配,可是線程做爲調度運行的獨立單位,僅僅攜帶自身運行的必備的一丁點資源。

對比

線程具備許多傳統進程所具備的特徵,因此又稱爲輕型進程(Light-Weight Process)或進程元
相應地把傳統進程稱爲重型進程(Heavy-Weight Process),傳統進程至關於只有一個線程的任務。
在引入了線程的操做系統中,一般一個進程都擁有若干個線程,至少也有一個線程。
image_5c5bab07_3789
併發性
傳統的OS系統,進程之間能夠併發執行,引入線程概念的OS,不只僅進程間能夠併發執行,一個進程中的線程也能夠併發執行,不一樣進程中的線程也能夠併發執行
獨立性
同一進程中的多個線程獨立性比不一樣進程間的獨立性差不少。
每一個進程都是獨立的地址空間和資源,同一進程下多線程他們共享進程下的資源,並且一般他們每每是用來相互合做的,每一個線程均可以訪問所在進程的全部地址空間,好比一個線程打開的文件,能夠被其餘線程讀寫。
調度性
傳統OS,進程做爲資源分配和調度分派的基本單位,進程是能夠獨立運行的基本單位,不過進程調度切換時空開銷大
引入線程的OS,線程是運行調度和分派的基本單位,線程纔是獨立運行的基本單位,線程切換時,僅僅須要保存和設置少許寄存器內容,代價遠遠小於進程切換,不過須要注意是同一個進程內線程切換不會進程切換,可是不一樣進程中的線程進程切換,仍舊會致使進程切換。
擁有資源
進程擁有資源,而且做爲系統中擁有資源的獨立基本單位。
線程自身不擁有系統資源,僅僅擁有一點必不可少的,獨立運行須要的資源,好比線程中的TCB。
除了自身的丁點兒資源外,共享所屬進程的資源,同一個進程下全部線程,擁有相同的地址空間。
多處理器支持
傳統進程(或者說單線程進程)只能運行於一個處理機上,無論有多少個處理機;
可是對於多線程進程,就能夠將一個進程中的多個線程分配到多個處理機上,並行運行
簡言之,多線程可讓多核CPU充分發揮性能並行運行。
系統開銷
進程和線程的建立撤銷,系統都要爲止分配和回收資源,好比內存空間、IO設備等,進程和線程的上下文切換,系統也都須要付出必定的時空開銷。
可是,線程相關的開銷明顯小於進程。

線程簡介

各線程之間也是存在資源共享和相互合做的,線程在運行時也是間斷的,輪轉切換的。
線程也是有運行狀態的,這一點與進程並無本質區別,最主要的狀態也是就緒、執行、阻塞
進程的控制核心信息保存在PCB中,線程也有對應的組成---TCB,全部用於控制和管理線程的信息都保存在TCB中
 
image_5c5bab07_4ef4
 
線程儘管是另一種徹底不一樣的事物,可是畢竟是從進程的概念演化而來,也是操做系統對程序運行抽象的一部分,因此,線程必然與進程有着不少的類似點

線程實現

線程的實現主要有三種形式
  • 內核支持
  • 用戶級線程
  • 另外就是兩者的組合

 

從上面的分析中能夠看得出來,內核支持和用戶級都有各自明顯的缺點和優勢。
有些操做系統把用戶級線程和內核支持線程兩種方式進行組合,提供了組合方式ULT/KST 線程。
在組合方式線程系統中, 內核支持多KST線程的創建、調度和管理,同時,也容許用戶應用程序創建、調度和管理用戶級線程。
一些內核支持線程對應多個用戶級線程,程序員可按應用須要和機器配置對內核支持線程數目進行調整,以達到較好的效果。
組合方式線程中,同一個進程內的多個線程能夠同時在多處理器上並行執行,並且在阻塞一個線程時,並不須要將整個進程阻塞。
因此,組合方式多線程機制可以結合 KST和 ULT二者的優勢,並克服了其各自的不足。 

線程的同步與通訊

關於進程的同步與通訊的相關邏輯原理,對於進程的同步與通訊絕大多數都是適用的。
針對於這些原理,多線程OS也提供了多種同步機制,如互斥鎖、條件變量、計數信號量以及多讀、單寫鎖等。

信號量機制

進程中的信號量機制徹底適合多線程同步
根據用法分爲兩種
  • 私用信號量(private samephore)
  • 公用信號量(public semaphort)
系統運行中,有多個進程,進程中又有多個線程。
若是是爲了同一進程中多個線程同步設置的信號量,量屬於特定的進程全部,這就叫作私用,OS並不知道私用信號量的存在。
若是是爲了避免同進程或者不一樣進程中的線程之間而設置的,就叫作公用。其數據結構是存放在受保護的系統存儲區中,由OS爲它分配空間並進行管理,故也稱爲系統信號量。

互斥鎖(mutex)

互斥鎖是一種比較簡單的、用於實現線程間對資源互斥訪問的機制
互斥鎖能夠有兩種狀態
  • 開鎖(unlock)
  • 關鎖(lock)
當一個線程須要讀/寫一個共享數據段時,須要對mutex進行上鎖,離開時須要解鎖。
上鎖時,首先校驗 mutex 的狀態,若是它已處於關鎖狀態,則試圖訪問該數據段的線程將被阻塞;若是 mutex處於開鎖狀態,則將 mutex 上鎖後便去讀/寫該數據段。
線程完成操做後,必須將 mutex 解鎖,同時還須要將阻塞在該互斥鎖上的一個線程喚醒,其它的線程仍被阻塞在等待mutex打開的隊列上。
另外,爲了減小線程被阻塞的機會,在有的系統中還提供了一種用於 mutex 上的操做命令 Trylock。
顧名思義,並不會由於沒法進入而阻塞,若 mutex 處於上鎖狀態,則 Trylock 並不會阻塞該線程,而只是返回一個指示操做失敗的狀態碼。

條件變量

在許多狀況下,只利用 mutex 來實現互斥訪問可能會引發死鎖,好比A線程請求資源順序爲R1,R2,B線程請求資源順序爲R2,R1
若是A對mutex 1上鎖成功進入臨界區後,須要獲取R2的鎖mutex 2,但是此時B得到了資源R2,對mutex 2已經上鎖,此時,A等待mutex 2 B等待mutex 1,造成了死鎖
因此說,鎖,應該是僅僅用於在條件成立時進行操做時的一個同步保障,而不能在整個過程當中都依靠鎖
能夠藉助於條件變量,就是條件
每個條件變量一般都與一個互斥鎖一塊兒使用,單純的互斥鎖用於短時間鎖定,主要是用來保證對臨界區的互斥進入。
而條件變量則用於線程的長期等待,直至所等待的資源成爲可用的資源。

申請

Lock mutex                  
while (條件狀態不知足) {
        wait(condition variable);//釋放鎖,線程掛起等待,直到條件知足通知;
}
臨界區其餘操做
unlock mutex; 

釋放

Lock mutex
一些操做
unlock mutex;
wakeup(condition variable);
簡言之,藉助於條件變量用於控制長時間的等待,鎖用於控制對資源的同步。

總結

本文對線程進行了很是簡單的介紹,線程之於進程在不少的方面有着極其相似的邏輯,尤爲是從調度的視角看。
畢竟線程就是對進程中關於調度部分的獨立抽象。
只要可以理解進程和線程的目的就可以很好地理解他們類似的緣由,由於都是操做系統對於程序運行的抽象描述,線程是進程的更加細粒度的掌控。
在換句話說就是操做系統的角度對程序的執行抽象爲:「資源的分配」「調度」
最初這兩個概念都是加諸於進程這個概念上,後續爲了更加高效將兩個概念進行了拆分,就是這樣
因此說,對於原先介紹的進程的相關概念中關於調度部分的絕大多數理論,都是適用於線程概念的
相關文章
相關標籤/搜索