當(dāng)前位置:首頁 > 百科知識 > 工控 > 正文

線程

線程,有時被稱為輕量級進(jìn)程(Lightweight Process,LWP),是程序執(zhí)行流的最小單元。一個標(biāo)準(zhǔn)的線程由線程ID,當(dāng)前指令指針(PC),寄存器集合和堆棧組成。另外,線程是進(jìn)程中的一個實體,是被系統(tǒng)獨立調(diào)度和分派的基本單位,線程自己不擁有系統(tǒng)資源,只擁有一點兒在運行中必不可少的資源,但它可與同屬一個進(jìn)程的其它線程共享進(jìn)程所擁有的全部資源。一個線程可以創(chuàng)建和撤消另一個線程,同一進(jìn)程中的多個線程之間可以并發(fā)執(zhí)行。由于線程之間的相互制約,致使線程在運行中呈現(xiàn)出間斷性。線程也有就緒、阻塞和運行三種基本狀態(tài)。就緒狀態(tài)是指線程具備運行的所有條件,邏輯上可以運行,在等待處理機;運行狀態(tài)是指線程占有處理機正在運行;阻塞狀態(tài)是指線程在等待一個事件(如某個信號量),邏輯上不可執(zhí)行。每一個程序都至少有一個線程,若程序只有一個線程,那就是程序本身。 線程是程序中一個單一的順序控制流程。進(jìn)程內(nèi)一個相對獨立的、可調(diào)度的執(zhí)行單元,是系統(tǒng)獨立調(diào)度和分派CPU的基本單位指運行中的程序的調(diào)度單位。在單個程序中同時運行多個線程完成不同的工作,稱為多線程。

發(fā)展簡史

  線程的引入:

  60年代,在OS中能擁有資源和獨立運行的基本單位是進(jìn)程,然而隨著計算機技術(shù)的發(fā)展,進(jìn)程出現(xiàn)了很多弊端,一是由于進(jìn)程是資源擁有者,創(chuàng)建、撤消與切換存在較大的時空開銷,因此需要引入輕型進(jìn)程;二是由于對稱多處理機(SMP)出現(xiàn),可以滿足多個運行單位,而多個進(jìn)程并行開銷過大。

  因此在80年代,出現(xiàn)了能獨立運行的基本單位——線程(Threads)。

適用范圍

  1.服務(wù)器中的文件管理或通信控制

  線程

  線程

  2.前后臺處理

  3.異步處理

特點

  線程的使用

  線程的使用

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

  1)輕型實體

  線程中的實體基本上不擁有系統(tǒng)資源,只是有一點必不可少的、能保證獨立運行的資源。

  線程的實體包括程序、數(shù)據(jù)和TCB。線程是動態(tài)概念,它的動態(tài)特性由線程控制塊TCB(Thread Control Block)描述。TCB包括以下信息:

  (1)線程狀態(tài)。

  (2)當(dāng)線程不運行時,被保存的現(xiàn)場資源。

 ?。?)一組執(zhí)行堆棧。

 ?。?)存放每個線程的局部變量主存區(qū)。

 ?。?)訪問同一個進(jìn)程中的主存和其它資源。

  用于指示被執(zhí)行指令序列的程序計數(shù)器、保留局部變量、少數(shù)狀態(tài)參數(shù)和返回地址等的一組寄存器和堆棧。

  2)獨立調(diào)度和分派的基本單位。

  在多線程OS中,線程是能獨立運行的基本單位,因而也是獨立調(diào)度和分派的基本單位。由于線程很“輕”,故線程的切換非常迅速且開銷?。ㄔ谕贿M(jìn)程中的)。

  3)可并發(fā)執(zhí)行。

  在一個進(jìn)程中的多個線程之間,可以并發(fā)執(zhí)行,甚至允許在一個進(jìn)程中所有線程都能并發(fā)執(zhí)行;同樣,不同進(jìn)程中的線程也能并發(fā)執(zhí)行,充分利用和發(fā)揮了處理機與外圍設(shè)備并行工作的能力。

  4)共享進(jìn)程資源。

  在同一進(jìn)程中的各個線程,都可以共享該進(jìn)程所擁有的資源,這首先表現(xiàn)在:所有線程都具有相同的地址空間(進(jìn)程的地址空間),這意味著,線程可以訪問該地址空間的每一個虛地址;此外,還可以訪問進(jìn)程所擁有的已打開文件、定時器、信號量機構(gòu)等。由于同一個進(jìn)程內(nèi)的線程共享內(nèi)存和文件,所以線程之間互相通信不必調(diào)用內(nèi)核。

與進(jìn)程比較

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

  另外,進(jìn)程也是搶占處理機的調(diào)度單位,它擁有一個完整的虛擬地址空間。當(dāng)進(jìn)程發(fā)生調(diào)度時,不同的進(jìn)程擁有不同的虛擬地址空間,而同一進(jìn)程內(nèi)的不同線程共享同一地址空間。

  與進(jìn)程相對應(yīng),線程與資源分配無關(guān),它屬于某一個進(jìn)程,并與進(jìn)程內(nèi)的其他線程一起共享進(jìn)程的資源。

  線程只由相關(guān)堆棧(系統(tǒng)棧或用戶棧)寄存器和線程控制表TCB組成。寄存器可被用來存儲線程內(nèi)的局部變量,但不能存儲其他線程的相關(guān)變量。

  通常在一個進(jìn)程中可以包含若干個線程,它們可以利用進(jìn)程所擁有的資源。在引入線程的操作系統(tǒng)中,通常都是把進(jìn)程作為分配資源的基本單位,而把線程作為獨立運行和獨立調(diào)度的基本單位。由于線程比進(jìn)程更小,基本上不擁有系統(tǒng)資源,故對它的調(diào)度所付出的開銷就會小得多,能更高效的提高系統(tǒng)內(nèi)多個程序間并發(fā)執(zhí)行的程度,從而顯著提高系統(tǒng)資源的利用率和吞吐量。因而近年來推出的通用操作系統(tǒng)都引入了線程,以便進(jìn)一步提高系統(tǒng)的并發(fā)性,并把它視為現(xiàn)代操作系統(tǒng)的一個重要指標(biāo)。

  線程與進(jìn)程的區(qū)別可以歸納為以下4點:

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

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

  3)調(diào)度和切換:線程上下文切換比進(jìn)程上下文切換要快得多。

  4)在多線程OS中,進(jìn)程不是一個可執(zhí)行的實體。

線程的同步

  線程的同步是Java多線程編程的難點,往往開發(fā)者搞不清楚什么是競爭資源、什么時候需要考慮同步,怎么同步等等問題,當(dāng)然,這些問題沒有很明確的答案,但有些原則問題需要考慮,是否有競爭資源被同時改動的問題?對于同步,在具體的Java代碼中需要完成以下兩個操作:把競爭訪問的資源標(biāo)識為private;同步哪些修改變量的代碼,使用synchronized關(guān)鍵字同步方法或代碼。當(dāng)然這不是唯一控制并發(fā)安全的途徑。synchronized關(guān)鍵字使用說明synchronized只能標(biāo)記非抽象的方法,不能標(biāo)識成員變量。為了演示同步方法的使用,構(gòu)建了一個信用卡賬戶,起初信用額為100w,然后模擬透支、存款等多個操作。顯然銀行賬戶User對象是個競爭資源,而多個并發(fā)操作的是賬戶方法oper(int x),當(dāng)然應(yīng)該在此方法上加上同步,并將賬戶的余額設(shè)為私有變量,禁止直接訪問。

  工作原理

  線程是進(jìn)程中的實體,一個進(jìn)程可以擁有多個線程,一個線程必須有一個父進(jìn)程。線程不擁有系統(tǒng)資源,只有運行必須的一些數(shù)據(jù)結(jié)構(gòu);它與父進(jìn)程的其它線程共享該進(jìn)程所擁有的全部資源。線程可以創(chuàng)建和撤消線程,從而實現(xiàn)程序的并發(fā)執(zhí)行。一般,線程具有就緒、阻塞和運行三種基本狀態(tài)。

  在多中央處理器的系統(tǒng)里,不同線程可以同時在不同的中央處理器上運行,甚至當(dāng)它們屬于同一個進(jìn)程時也是如此。大多數(shù)支持多處理器的操作系統(tǒng)都提供編程接口來讓進(jìn)程可以控制自己的線程與各處理器之間的關(guān)聯(lián)度(affinity)。

  有時候,線程也稱作輕量級進(jìn)程。就象進(jìn)程一樣,線程在程序中是獨立的、并發(fā)的執(zhí)行路徑,每個線程有它自己的堆棧、自己的程序計數(shù)器和自己的局部變量。但是,與分隔的進(jìn)程相比,進(jìn)程中的線程之間的隔離程度要小。它們共享內(nèi)存、文件句柄和其它每個進(jìn)程應(yīng)有的狀態(tài)。

  進(jìn)程可以支持多個線程,它們看似同時執(zhí)行,但互相之間并不同步。一個進(jìn)程中的多個線程共享相同的內(nèi)存地址空間,這就意味著它們可以訪問相同的變量和對象,而且它們從同一堆中分配對象。盡管這讓線程之間共享信息變得更容易,但您必須小心,確保它們不會妨礙同一進(jìn)程里的其它線程。

  Java 線程工具和 API看似簡單。但是,編寫有效使用線程的復(fù)雜程序并不十分容易。因為有多個線程共存在相同的內(nèi)存空間中并共享相同的變量,所以您必須小心,確保您的線程不會互相干擾。

  線程屬性

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

  線程體

  所有的操作都發(fā)生在線程體中,在Java中線程體是從Thread類繼承的run()方法,或?qū)崿F(xiàn)Runnable接口的類中的run()方法。當(dāng)線程產(chǎn)生并初始化后,實時系統(tǒng)調(diào)用它的run()方法。run()方法內(nèi)的代碼實現(xiàn)所產(chǎn)生線程的行為,它是線程的主要部分。

  線程狀態(tài)

  線程的狀態(tài)

  線程的狀態(tài)

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

  ●新線程態(tài)(New Thread)

  產(chǎn)生一個Thread對象就生成一個新線程。當(dāng)線程處于"新線程"狀態(tài)時,僅僅是一個空線程對象,它還沒有分配到系統(tǒng)資源。因此只能啟動或終止它。任何其他操作都會引發(fā)異常。例如,一個線程調(diào)用了new方法之后,并在調(diào)用start方法之前的處于新線程狀態(tài),可以調(diào)用start和stop方法。

  ●可運行態(tài)(Runnable)

  start()方法產(chǎn)生運行線程所必須的資源,調(diào)度線程執(zhí)行,并且調(diào)用線程的run()方法。在這時

  線程的生命狀態(tài)與周期

  線程的生命狀態(tài)與周期

  線程處于可運行態(tài)。該狀態(tài)不稱為運行態(tài)是因為這時的線程并不總是一直占用處理機。特別是對于只有一個處理機的PC而言,任何時刻只能有一個處于可運行態(tài)的線程占用處理 機。Java通過調(diào)度來實現(xiàn)多線程對處理機的共享。注意,如果線程處于Runnable狀態(tài),它也有可能不在運行,這是因為還有優(yōu)先級和調(diào)度問題。

  ●阻塞/非運行態(tài)(Not Runnable)

  當(dāng)以下事件發(fā)生時,線程進(jìn)入非運行態(tài)。

 ?、賡uspend()方法被調(diào)用;

  ②sleep()方法被調(diào)用;

  ③線程使用wait()來等待條件變量;

  ④線程處于I/O請求的等待。

  ●死亡態(tài)(Dead)

  當(dāng)run()方法返回,或別的線程調(diào)用stop()方法,線程進(jìn)入死亡態(tài)。通常Applet使用它的stop()方法來終止它產(chǎn)生的所有線程。

  線程的本操作:

  派生:線程在進(jìn)程內(nèi)派生出來,它即可由進(jìn)程派生,也可由線程派生。

  阻塞(Block):如果一個線程在執(zhí)行過程中需要等待某個事件發(fā)生,則被阻塞。

  激活(unblock):如果阻塞線程的事件發(fā)生,則該線程被激活并進(jìn)入就緒隊列。

  調(diào)度(schedule):選擇一個就緒線程進(jìn)入執(zhí)行狀態(tài)。

  結(jié)束(Finish):如果一個線程執(zhí)行結(jié)束,它的寄存器上下文以及堆棧內(nèi)容等將被釋放。

  圖2 線程的狀態(tài)與操作

  線程的另一個執(zhí)行特性是同步。線程中所使用的同步控制機制與進(jìn)程中所使用的同步控制機制相同。

  線程優(yōu)先級

  雖然我們說線程是并發(fā)運行的。然而事實常常并非如此。正如前面談到的,當(dāng)系統(tǒng)中只有一個CPU時,以某種順序在單CPU情況下執(zhí)行多線程被稱為調(diào)度(scheduling)。Java采用的是一種簡單、固定的調(diào)度法,即固定優(yōu)先級調(diào)度。這種算法是根據(jù)處于可運行態(tài)線程的相對優(yōu)先級來實行調(diào)度。當(dāng)線程產(chǎn)生時,它繼承原線程的優(yōu)先級。在需要時可對優(yōu)先級進(jìn)行修改。在任何時刻,如果有多條線程等待運行,系統(tǒng)選擇優(yōu)先級最高的可運行線程運行。只有當(dāng)它停止、自動放棄、或由于某種原因成為非運行態(tài)低優(yōu)先級的線程才能運行。如果兩個線程具有相同的優(yōu)先級,它們將被交替地運行?!ava實時系統(tǒng)的線程調(diào)度算法還是強制性的,在任何時刻,如果一個比其他線程優(yōu)先級都高的線程的狀態(tài)變?yōu)榭蛇\行態(tài),實時系統(tǒng)將選擇該線程來運行。一個應(yīng)用程序可以通過使用線程中的方法setPriority(int),來設(shè)置線程的優(yōu)先級大小。

  有線程進(jìn)入了就緒狀態(tài),需要有線程調(diào)度程序來決定何時執(zhí)行,根據(jù)優(yōu)先級來調(diào)度。


內(nèi)容來自百科網(wǎng)