1. 程式人生 > >線程概念簡介 什麽是線程 多線程上篇(七)

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

pri 獨立 ref 效果 訪問 one 至少 單純 其它

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

線程與進程對比

線程概念的發展

技術分享圖片 進程概念提出的目的就是為了多道程序並發執行,並發過程中必然意味著不斷地進程調度任務切換,但是他又是資源分配的獨立單位,也就是說他要背著資源來回跑。
舉個例子: 辦公室內,每個人都有一臺電腦,電腦就是資源 然後大家經常需要不斷地變換座位位置(比如大家都是哪裏需要去哪裏,客服缺人了,銷售就頂一個過去) 每個人都抱著自己的電腦來回的換位置方便?還是大家只是人員走動,電腦就使用那個位置的電腦方便? 進程也是有些類似的道理你帶著這麽多資源來回切換調度,必然會帶來更多的時&&空開銷 所以創建了線程的概念程序運行時所需的資源和程序的調度進行解耦 進程仍舊負責資源的獨立分配,但是線程作為調度運行的獨立單位,僅僅攜帶自身運行的必備的一丁點資源。

對比

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

線程簡介

各線程之間也是存在資源共享和相互合作的,線程在運行時也是間斷的,輪轉切換的。 線程也是有運行狀態的,這一點與進程並沒有本質區別,最主要的狀態也是就緒、執行、阻塞 進程的控制核心信息保存在PCB中,線程也有對應的組成---TCB,所有用於控制和管理線程的信息都保存在TCB中 技術分享圖片 線程盡管是另外一種完全不同的事物,但是畢竟是從進程的概念演化而來,也是操作系統對程序運行抽象的一部分,所以,線程必然與進程有著很多的相似點

線程實現

線程的實現主要有三種形式
  • 內核支持
  • 用戶級線程
  • 另外就是二者的組合
技術分享圖片

從上面的分析中可以看得出來,內核支持和用戶級都有各自明顯的缺點和優點。 有些操作系統把用戶級線程和內核支持線程兩種方式進行組合,提供了組合方式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); 簡言之,借助於條件變量用於控制長時間的等待,鎖用於控制對資源的同步。

總結

本文對線程進行了非常簡單的介紹,線程之於進程在很多的方面有著極其類似的邏輯,尤其是從調度的視角看。 畢竟線程就是對進程中關於調度部分的獨立抽象。 只要能夠理解進程和線程的目的就能夠很好地理解他們相似的原因,因為都是操作系統對於程序運行的抽象描述,線程是進程的更加細粒度的掌控。 在換句話說就是操作系統的角度對程序的執行抽象為:“資源的分配”“調度” 最初這兩個概念都是加諸於進程這個概念上,後續為了更加高效將兩個概念進行了拆分,就是這樣 所以說,對於原先介紹的進程的相關概念中關於調度部分的絕大多數理論,都是適用於線程概念的 原文地址:線程概念簡介 什麽是線程 多線程上篇(七)

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