線程

用手机看条目

出自 MBA智库百科(https://wiki.mbalib.com/)

目錄

什麼是線程

  線程是指進程中某個單一順序的控制流。 臺灣稱執行緒。線程是程式中一個單一的順序控制流程。在單個程式中同時運行多個線程完成不同的工作,稱為多線程。

線程的內容

  線程有時被稱為輕量級進程(Lightweight Process,LWP),是程式執行流的最小單元。一個標準的線程由線程ID,當前指令指針(PC),寄存器集合和堆棧組成。另外,線程是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程自己不擁有系統資源,只擁有一點兒在運行中必不可少的資源,但它可與同屬一個進程的其它線程共用進程所擁有的全部資源。一個線程可以創建和撤消另一個線程,同一進程中的多個線程之間可以併發執行。由於線程之間的相互制約,致使線程在運行中呈現出間斷性。線程也有就緒、阻塞和運行三種基本狀態。每一個程式都至少有一個線程,若程式只有一個線程,那就是程式本身。就象進程一樣,線程在程式中是獨立的、併發的執行路徑,每個線程有它自己的堆棧、自己的程式計數器和自己的局部變數。但是,與分隔的進程相比,進程中的線程之間的隔離程度要小。它們共用記憶體、文件句柄和其它每個進程應有的狀態。

  線程的工作原理是線程是進程中的實體,一個進程可以擁有多個線程,一個線程必須有一個父進程。線程不擁有系統資源,只有運行必須的一些數據結構;它與父進程的其它線程共用該進程所擁有的全部資源。線程可以創建和撤消線程,從而實現程式的併發執行。一般,線程具有就緒、阻塞和運行三種基本狀態。在多中央處理器的系統里,不同線程可以同時在不同的中央處理器上運行,甚至當它們屬於同一個進程時也是如此。大多數支持多處理器的操作系統都提供編程介面來讓進程可以控制自己的線程與各處理器之間的關聯度(affinity)。

線程的特點

  在多線程OS中,通常是在一個進程中包括多個線程,每個線程都是作為利用CPU的基本單位,是花費最小開銷的實體。線程具有以下屬性。

  • 輕型實體

  線程中的實體基本上不擁有系統資源,只是有一點必不可少的、能保證獨立運行的資源,比如,在每個線程中都應具有一個用於控制線程運行的線程式控制制塊TCB,用於指示被執行指令序列的程式計數器、保留局部變數、少數狀態參數和返回地址等的一組寄存器和堆棧。

  • 獨立調度和分派的基本單位。

  在多線程OS中,線程是能獨立運行的基本單位,因而也是獨立調度和分派的基本單位。由於線程很“輕”,故線程的切換非常迅速且開銷小(在同一進程中的)。

  • 可併發執行。

  在一個進程中的多個線程之間,可以併發執行,甚至允許在一個進程中所有線程都能併發執行;同樣,不同進程中的線程也能併發執行,充分利用和發揮了處理機與外圍設備並行工作的能力

  • 共用進程資源。

  在同一進程中的各個線程,都可以共用該進程所擁有的資源,這首先表現在:所有線程都具有相同的地址空間(進程的地址空間),這意味著,線程可以訪問該地址空間的每一個虛地址;此外,還可以訪問進程所擁有的已打開文件、定時器、信號量機構等。由於同一個進程內的線程共用記憶體和文件,所以線程之間互相通信不必調用內核。

線程的操作

  進程可以支持多個線程,它們看似同時執行,但互相之間並不同步。一個進程中的多個線程共用相同的記憶體地址空間,這就意味著它們可以訪問相同的變數和對象,而且它們從同一堆中分配對象。儘管這讓線程之間共用信息變得更容易,但您必須小心,確保它們不會妨礙同一進程里的其它線程。Java 線程工具和API看似簡單。但是,編寫有效使用線程的複雜程式並不十分容易。因為有多個線程共存在相同的記憶體空間中並共用相同的變數,所以必須小心,確保您的線程不會互相干擾。

  • 線程屬性

  為了正確有效地使用線程,必須理解線程的各個方面並瞭解Java 實時系統。必須知道如何提供線程體、線程的生命周期、實時系統如 何調度線程、線程組、什麼是幽靈線程(Demo nThread)。

  • 線程體

  所有的操作都發生線上程體中,在Java中線程體是從Thread類繼承的run()方法,或實現Runnable介面的類中的run()方法。當線程產生並初始化後,實時系統調用它的run()方法。run()方法內的代碼實現所產生線程的行為,它是線程的主要部分。

  • 線程的狀態

  表示了線程在它的生命周期內的任何時刻所能處的狀態以及引起狀態改變的方法。這圖並不是完整的有限狀態圖,但基本概括了線程中比較感興趣和普遍的方面。以下討論有關線程生命周期以此為據。

  • 新線程態(New Thread)

  產生一個Thread對象就生成一個新線程。當線程處於"新線程"狀態時,僅僅是一個空線程對象,它還沒有分配到系統資源。因此只能啟動或終止它。任何其他操作都會引發異常。例如,一個線程調用了new方法之後,併在調用start方法之前的處於新線程狀態,可以調用start和stop方法。

  • 可運行態(Runnable)

  start()方法產生運行線程所必須的資源,調度線程執行,並且調用線程的run()方法。在這時

  • 線程的生命狀態與周期

  線程處於可運行態。該狀態不稱為運行態是因為這時的線程並不總是一直占用處理機。特別是對於只有一個處理機的PC而言,任何時刻只能有一個處於可運行態的線程占用處理 機。Java通過調度來實現多線程對處理機的共用。註意,如果線程處於Runnable狀態,它也有可能不在運行,這是因為還有優先順序和調度問題。

  • 阻塞/非運行態(Not Runnable)

  當以下事件發生時,線程進入非運行態。

  1. suspend()方法被調用;
  2. sleep()方法被調用;
  3. 線程使用wait()來等待條件變數;
  4. 線程處於I/O請求的等待。
  • 死亡態(Dead)

  當run()方法返回,或別的線程調用stop()方法,線程進入死亡態。通常Applet使用它的stop()方法來終止它產生的所有線程。

  • 線程的本操作
  1. 派生:線程在進程內派生出來,它即可由進程派生,也可由線程派生。
  2. 阻塞(Block):如果一個線程在執行過程中需要等待某個事件發生,則被阻塞。
  3. 激活(unblock):如果阻塞線程的事件發生,則該線程被激活併進入就緒隊列。
  4. 調度(schedule):選擇一個就緒線程進入執行狀態。
  5. 結束(Finish):如果一個線程執行結束,它的寄存器上下文以及堆棧內容等將被釋放。

  線程的另一個執行特性是同步。線程中所使用的同步控制機制與進程中所使用的同步控制機制相同。

  • 線程優先順序

  雖然說線程是併發運行的。然而事實常常並非如此。正如前面談到的,當系統中只有一個CPU時,以某種順序在單CPU情況下執行多線程被稱為調度(scheduling)。Java採用的是一種簡單、固定的調度法,即固定優先順序調度。這種演算法是根據處於可運行態線程的相對優先順序來實行調度。當線程產生時,它繼承原線程的優先順序。在需要時可對優先順序進行修改。在任何時刻,如果有多條線程等待運行,系統選擇優先順序最高的可運行線程運行。只有當它停止、自動放棄、或由於某種原因成為非運行態低優先順序的線程才能運行。如果兩個線程具有相同的優先順序,它們將被交替地運行。Java實時系統的線程調度演算法還是強制性的,在任何時刻,如果一個比其他線程優先順序都高的線程的狀態變為可運行態,實時系統將選擇該線程來運行。一個應用程式可以通過使用線程中的方法setPriority(int),來設置線程的優先順序大小。

  • 線程的組成
  1. 一組代表處理器狀態的CPU寄存器中的內容
  2. 兩個棧,一個用於當線程在內核模式下執行的時候,另一個用於線程在用戶模式下執行的時候。
  3. 一個被稱為線程局部存儲器(TLS,thread-local storage)的私有儲存區域,各個子系統、運行庫和DLL都會用到該儲存區域。
  4. 一個被稱為線程ID(thread ID,線程標識符)的唯一標識符(在內部也被稱為客戶ID——進程ID和線程ID是在同一個名字空間中生產的,所以它們永遠 不會重疊)。
  5. 有時候線程也有它們自己的安全環境,如果多線程伺服器應用程式要模仿其客戶的安全環境,則往往可以利用線程的安全環境。
  • 幽靈線程

  任何一個Java線程都能成為幽靈線程。它是作為運行於同一個進程內的對象和線程的服務提供者。例如,HotJava瀏覽器有一個稱為" 後臺圖片閱讀器"的幽靈線程,它為需要圖片的對象和線程從文件系統或網路讀入圖片。 幽靈線程是應用中典型的獨立線程。它為同一應用中的其他對象和線程提供服務。幽靈線程的run()方法一般都是無限迴圈,等待服務請求。

  • 線程組

  每個Java線程都是某個線程組的成員。線程組提供一種機制,使得多個線程集於一個對象內,能對它們實行整體操作。譬如,你能用一個方法調用來啟動或掛起組內的所有線程。Java線程組由ThreadGroup類實現。 當線程產生時,可以指定線程組或由實時系統將其放入某個預設的線程組內。線程只能屬於一個線程組,並且當線程產生後不能改變它所屬的線程組。

  • 多線程

  對於多線程的好處這就不多說了。但是,它同樣也帶來了某些新的麻煩。只要在設計程式時特別小心留意,剋服這些麻煩並不算太困難。在生成線程時必須將線程放在指定的線程組,也可以放在預設的線程組中,預設的就是生成該線程的線程所在的線程組。一旦一個線程加入了某個線程組,不能被移出這個組。

  • 同步線程

  許多線程在執行中必須考慮與其他線程之間共用數據協調執行狀態。這就需要同步機制。在Java中每個對象都有一把鎖與之對應。但Java不提供單獨的lock和unlock操作。它由高層的結構隱式實現,來保證操作的對應。(然而,我們註意到Java虛擬機提供單獨的monito renter和monitorexit指令來實現lock和unlock操作。

線程和進程的關係

  進程是資源分配的基本單位。所有與該進程有關的資源,都被記錄在進程式控制制塊PCB中。以表示該進程擁有這些資源或正在使用它們。

  另外,進程也是搶占處理機的調度單位,它擁有一個完整的虛擬地址空間。當進程發生調度時,不同的進程擁有不同的虛擬地址空間,而同一進程內的不同線程共用同一地址空間。與進程相對應,線程與資源分配無關,它屬於某一個進程,並與進程內的其他線程一起共用進程的資源。線程只由相關堆棧(系統棧或用戶棧)寄存器和線程控製表TCB組成。寄存器可被用來存儲線程內的局部變數,但不能存儲其他線程的相關變數。通常在一個進程中可以包含若幹個線程,它們可以利用進程所擁有的資源。在引入線程的操作系統中,通常都是把進程作為分配資源的基本單位,而把線程作為獨立運行和獨立調度的基本單位。由於線程比進程更小,基本上不擁有系統資源,故對它的調度所付出的開銷就會小得多,能更高效的提高系統內多個程式間併發執行的程度,從而顯著提高系統資源的利用率和吞吐量。因而近年來推出的通用操作系統都引入了線程,以便進一步提高系統的併發性,並把它視為現代操作系統的一個重要指標

  1)地址空間和其它資源(如打開文件):進程間相互獨立,同一進程的各線程間共用。某進程內的線程在其它進程不可見。

  2)通信進程間通信IPC,線程間可以直接讀寫進程數據段(如全局變數)來進行通信——需要進程同步和互斥手段的輔助,以保證數據的一致性。

  3)調度和切換:線程上下文切換比進程上下文切換要快得多。

  4)在多線程OS中,進程不是一個可執行的實體。

相關條目

本條目對我有幫助3
MBA智库APP

扫一扫,下载MBA智库APP

分享到:
  如果您認為本條目還有待完善,需要補充新內容或修改錯誤內容,請編輯條目

本条目由以下用户参与贡献

寒曦,刘维燎.

評論(共0條)

提示:評論內容為網友針對條目"線程"展開的討論,與本站觀點立場無關。

發表評論請文明上網,理性發言並遵守有關規定。

MBA智库
打开APP

以上内容根据网友推荐自动排序生成