發展簡史
線程的引入:
60年代,在OS中能擁有資源和獨立運行的基本單位是進程,然而随着計算機技術的發展,進程出現了很多弊端,一是由于進程是資源擁有者,創建、撤消與切換存在較大的時空開銷,因此需要引入輕型進程;二是由于對稱多處理機(SMP)出現,可以滿足多個運行單位,而多個進程并行開銷過大。
因此在80年代,出現了能獨立運行的基本單位——線程(Threads)。
适用範圍
1、服務器中的文件管理或通信控制
2、前後台處理
3、異步處理
特點
在多線程OS中,通常是在一個進程中包括多個線程,每個線程都是作為利用CPU的基本單位,是花費最小開銷的實體。線程具有以下屬性。
1、輕型實體
線程中的實體基本上不擁有系統資源,隻是有一點必不可少的、能保證獨立運行的資源。
線程的實體包括程序、數據和TCB。線程是動态概念,它的動态特性由線程控制塊TCB(ThreadControlBlock)描述。TCB包括以下信息:
(1)線程狀态。
(2)當線程不運行時,被保存的現場資源。
(3)一組執行堆棧。
(4)存放每個線程的局部變量主存區。
(5)訪問同一個進程中的主存和其它資源。
用于指示被執行指令序列的程序計數器、保留局部變量、少數狀态參數和返回地址等的一組寄存器和堆棧。
2、獨立調度和分派的基本單位。
在多線程OS中,線程是能獨立運行的基本單位,因而也是獨立調度和分派的基本單位。由于線程很“輕”,故線程的切換非常迅速且開銷小(在同一進程中的)。
3、可并發執行。
在一個進程中的多個線程之間,可以并發執行,甚至允許在一個進程中所有線程都能并發執行;同樣,不同進程中的線程也能并發執行,充分利用和發揮了處理機與外圍設備并行工作的能力。
4、共享進程資源。
在同一進程中的各個線程,都可以共享該進程所擁有的資源,這首先表現在:所有線程都具有相同的地址空間(進程的地址空間),這意味着,線程可以訪問該地址空間的每一個虛地址;此外,還可以訪問進程所擁有的已打開文件、定時器、信号量機構等。由于同一個進程内的線程共享内存和文件,所以線程之間互相通信不必調用内核。
與進程比較
進程是資源分配的基本單位。所有與該進程有關的資源,都被記錄在進程控制塊PCB中。以表示該進程擁有這些資源或正在使用它們。
另外,進程也是搶占處理機的調度單位,它擁有一個完整的虛拟地址空間。當進程發生調度時,不同的進程擁有不同的虛拟地址空間,而同一進程内的不同線程共享同一地址空間。
與進程相對應,線程與資源分配無關,它屬于某一個進程,并與進程内的其他線程一起共享進程的資源。
線程隻由相關堆棧(系統棧或用戶棧)寄存器和線程控制表TCB組成。寄存器可被用來存儲線程内的局部變量,但不能存儲其他線程的相關變量。
通常在一個進程中可以包含若幹個線程,它們可以利用進程所擁有的資源。在引入線程的操作系統中,通常都是把進程作為分配資源的基本單位,而把線程作為獨立運行和獨立調度的基本單位。由于線程比進程更小,基本上不擁有系統資源,故對它的調度所付出的開銷就會小得多,能更高效的提高系統内多個程序間并發執行的程度,從而顯著提高系統資源的利用率和吞吐量。因而近年來推出的通用操作系統都引入了線程,以便進一步提高系統的并發性,并把它視為現代操作系統的一個重要指标。
線程與進程的區别可以歸納為以下4點:
1、地址空間和其它資源(如打開文件):進程間相互獨立,同一進程的各線程間共享。某進程内的線程在其它進程不可見。
2、通信:進程間通信IPC,線程間可以直接讀寫進程數據段(如全局變量)來進行通信——需要進程同步和互斥手段的輔助,以保證數據的一緻性。
3、調度和切換:線程上下文切換比進程上下文切換要快得多。
4、在多線程OS中,進程不是一個可執行的實體。
守護線程
守護線程是特殊的線程,一般用于在後台為其他線程提供服務.
Java中,isDaemon():判斷一個線程是否為守護線程.
Java中,setDaemon():設置一個線程為守護線程.
C#守護線程
類1守護線程類
線程的同步
線程的同步是Java多線程編程的難點,往往開發者搞不清楚什麼是競争資源、什麼時候需要考慮同步,怎麼同步等等問題,當然,這些問題沒有很明确的答案,但有些原則問題需要考慮,是否有競争資源被同時改動的問題?對于同步,在具體的Java代碼中需要完成以下兩個操作:把競争訪問的資源标識為private;同步哪些修改變量的代碼,使用synchronized關鍵字同步方法或代碼。當然這不是唯一控制并發安全的途徑。synchronized關鍵字使用說明synchronized隻能标記非抽象的方法,不能标識成員變量。為了演示同步方法的使用,構建了一個信用卡賬戶,起初信用額為100w,然後模拟透支、存款等多個操作。顯然銀行賬戶User對象是個競争資源,而多個并發操作的是賬戶方法oper(intx),當然應該在此方法上加上同步,并将賬戶的餘額設為私有變量,禁止直接訪問。
工作原理
線程是進程中的實體,一個進程可以擁有多個線程,一個線程必須有一個父進程。線程不擁有系統資源,隻有運行必須的一些數據結構;它與父進程的其它線程共享該進程所擁有的全部資源。線程可以創建和撤消線程,從而實現程序的并發執行。一般,線程具有就緒、阻塞和運行三種基本狀态。
在多中央處理器的系統裡,不同線程可以同時在不同的中央處理器上運行,甚至當它們屬于同一個進程時也是如此。大多數支持多處理器的操作系統都提供編程接口來讓進程可以控制自己的線程與各處理器之間的關聯度(affinity)。
有時候,線程也稱作輕量級進程。就象進程一樣,線程在程序中是獨立的、并發的執行路徑,每個線程有它自己的堆棧、自己的程序計數器和自己的局部變量。但是,與分隔的進程相比,進程中的線程之間的隔離程度要小。它們共享内存、文件句柄和其它每個進程應有的狀态。
進程可以支持多個線程,它們看似同時執行,但互相之間并不同步。一個進程中的多個線程共享相同的内存地址空間,這就意味着它們可以訪問相同的變量和對象,而且它們從同一堆中分配對象。盡管這讓線程之間共享信息變得更容易,但您必須小心,确保它們不會妨礙同一進程裡的其它線程。
Java線程工具和API看似簡單。但是,編寫有效使用線程的複雜程序并不十分容易。因為有多個線程共存在相同的内存空間中并共享相同的變量,所以您必須小心,确保您的線程不會互相幹擾。
線程屬性
為了正确有效地使用線程,必須理解線程的各個方面并了解Java實時系統。必須知道如何提供線程體、線程的生命周期、實時系統如何調度線程、線程組、什麼是幽靈線程(DemonThread)。
線程體
所有的操作都發生在線程體中,在Java中線程體是從Thread類繼承的run()方法,或實現Runnable接口的類中的run()方法。當線程産生并初始化後,實時系統調用它的run()方法。run()方法内的代碼實現所産生線程的行為,它是線程的主要部分。
線程狀态
附圖表示了線程在它的生命周期内的任何時刻所能處的狀态以及引起狀态改變的方法。這圖并不是完整的有限狀态圖,但基本概括了線程中比較感興趣和普遍的方面。以下讨論有關線程生命周期以此為據。
新線程态(NewThread)
産生一個Thread對象就生成一個新線程。當線程處于"新線程"狀态時,僅僅是一個空線程對象,它還沒有分配到系統資源。因此隻能啟動或終止它。任何其他操作都會引發異常。例如,一個線程調用了new方法之後,并在調用start方法之前的處于新線程狀态,可以調用start和stop方法。
可運行态(Runnable)
start()方法産生運行線程所必須的資源,調度線程執行,并且調用線程的run()方法。在這時線程處于可運行态。該狀态不稱為運行态是因為這時的線程并不總是一直占用處理機。特别是對于隻有一個處理機的PC而言,任何時刻隻能有一個處于可運行态的線程占用處理機。Java通過調度來實現多線程對處理機的共享。注意,如果線程處于Runnable狀态,它也有可能不在運行,這是因為還有優先級和調度問題。
阻塞/非運行态(NotRunnable)
當以下事件發生時,線程進入非運行态。
1、suspend()方法被調用;
2、sleep()方法被調用;
3、線程使用wait()來等待條件變量;
4、線程處于I/O請求的等待。
死亡态(Dead)
當run()方法返回,或别的線程調用stop()方法,線程進入死亡态。通常Applet使用它的stop()方法來終止它産生的所有線程。
線程的本操作:
派生:線程在進程内派生出來,它即可由進程派生,也可由線程派生。
阻塞(Block):如果一個線程在執行過程中需要等待某個事件發生,則被阻塞。
激活(unblock):如果阻塞線程的事件發生,則該線程被激活并進入就緒隊列。
調度(schedule):選擇一個就緒線程進入執行狀态。
結束(Finish):如果一個線程執行結束,它的寄存器上下文以及堆棧内容等将被釋放。
線程的狀态與操作
線程的另一個執行特性是同步。線程中所使用的同步控制機制與進程中所使用的同步控制機制相同。
線程優先級
雖然我們說線程是并發運行的。然而事實常常并非如此。正如前面談到的,當系統中隻有一個CPU時,以某種順序在單CPU情況下執行多線程被稱為調度(scheduling)。Java采用的是一種簡單、固定的調度法,即固定優先級調度。這種算法是根據處于可運行态線程的相對優先級來實行調度。當線程産生時,它繼承原線程的優先級。在需要時可對優先級進行修改。在任何時刻,如果有多條線程等待運行,系統選擇優先級最高的可運行線程運行。隻有當它停止、自動放棄、或由于某種原因成為非運行态低優先級的線程才能運行。如果兩個線程具有相同的優先級,它們将被交替地運行ava實時系統的線程調度算法還是強制性的,在任何時刻,如果一個比其他線程優先級都高的線程的狀态變為可運行态,實時系統将選擇該線程來運行。一個應用程序可以通過使用線程中的方法setPriority(int),來設置線程的優先級大小。
有線程進入了就緒狀态,需要有線程調度程序來決定何時執行,根據優先級來調度。
線程中的join()可以用來邀請其他線程先執行(示例代碼如下):
packageorg.thread.test;publicclassJoin01implementsRunnable{publicstaticvoidmain(String[]args){for(inti=0;i
yield()告訴系統"把自己的CPU時間讓掉,讓其他線程或者自己運行",示例代碼如下:
packageorg.thread.test;
publicclassYield01
{
publicstaticvoidmain(String[]args)
{
YieldFirstyf=newYieldFirst();
YieldSecondys=newYieldSecond();
YieldThirdyt=newYieldThird();
yf.start();ys.start();yt.start();
}
}
classYieldFirstextendsThread
{
@Overridepublicvoidrun()
{
for(inti=0;i
{
System.out.println("第一個線程第"+(i+1)+"次運行.");//讓當前線程暫停yield();
}
}
}
classYieldSecondextendsThread
{
@Overridepublicvoidrun()
{
for(inti=0;i
{
System.out.println("第二個線程第"+(i+1)+"次運行.");//讓當前線程暫停yield();
}
}
classYieldThirdextendsThread
{
@Overridepublicvoidrun(){for(inti=0;i
{
System.out.println("第三個線程第"+(i+1)+"次運行.");//讓當前線程暫停yield();
}
}
幽靈線程
任何一個Java線程都能成為幽靈線程。它是作為運行于同一個進程内的對象和線程的服務提供者。例如,HotJava浏覽器有一個稱為"後台圖片閱讀器"的幽靈線程,它為需要圖片的對象和線程從文件系統或網絡讀入圖片。幽靈線程是應用中典型的獨立線程。它為同一應用中的其他對象和線程提供服務。幽靈線程的run()方法一般都是無限循環,等待服務請求。
線程組
每個Java線程都是某個線程組的成員。線程組提供一種機制,使得多個線程集于一個對象内,能對它們實行整體操作。譬如,你能用一個方法調用來啟動或挂起組内的所有線程。Java線程組由ThreadGroup類實現。
當線程産生時,可以指定線程組或由實時系統将其放入某個缺省的線程組内。線程隻能屬于一個線程組,并且當線程産生後不能改變它所屬的線程組。
對于多線程的好處這就不多說了。但是,它同樣也帶來了某些新的麻煩。隻要在設計程序時特别小心留意,克服這些麻煩并不算太困難。在生成線程時必須将線程放在指定的線程組,也可以放在缺省的線程組中,缺省的就是生成該線程的線程所在的線程組。一旦一個線程加入了某個線程組,不能被移出這個組。
同步線程
許多線程在執行中必須考慮與其他線程之間共享數據或協調執行狀态。這就需要同步機制。在Java中每個對象都有一把鎖與之對應。但Java不提供單獨的lock和unlock操作。它由高層的結構隐式實現,來保證操作的對應。(然而,我們注意到Java虛拟機提供單獨的monitorenter和monitorexit指令來實現lock和
unlock操作。)synchronized語句計算一個對象引用,試圖對該對象完成鎖操作,并且在完成鎖操作前停止處理。當鎖操作完成synchronized語句體得到執行。當語句體執行完畢(無論正常或異常),解鎖操作自動完成。作為面向對象的語言,synchronized經常與方法連用。一種比較好的辦法是,如果某個變量由一個線程賦值并由别的線程引用或賦值,那麼所有對該變量的訪問都必須在某個synchromized語句或synchronized方法内。
在此假設一種情況:線程1與線程2都要訪問某個數據區,并且要求線程1的訪問先于線程2,則這時僅用synchronized是不能解決問題的。這在Unix或WindowsNT中可用Simaphore來實現。而Java并不提供。在Java中提供的是wait()和notify()機制。使用如下:
synchronizedmethod_1(/*……*/){//calledbythread1.//accessdataareaavailable=true;notify();}synchronizedmethod_2(/*……*/){//calledbythread2.while(!available)try{wait();//waitfornotify().}catch(InterruptedExceptione){}//accessdataarea}
其中available是類成員變量,置初值為false。
如果在method-2中檢查available為假,則調用wait()。wait()的作用是使線程2進入非運行态,并且解鎖。在這種情況下,method-1可以被線程1調用。當執行notify()後。線程2由非運行态轉變為可運行态。當method-1調用返回後。線程2可重新對該對象加鎖,加鎖成功後執行wait()返回後的指令。這種機制也能适用于其他更複雜的情況。
死鎖
如果程序中有幾個競争資源的并發線程,那麼保證均衡是很重要的。系統均衡是指每個線程在執行過程中都能充分訪問有限的資源。系統中沒有餓死和死鎖的線程。Java并不提供對死鎖的檢測機制。對大多數的Java程序員來說防止死鎖是一種較好的選擇。最簡單的防止死鎖的方法是對競争的資源引入序号,如果一個線程需要幾個資源,那麼它必須先得到小序号的資源,再申請大序号的資源。
優化
Java的多線程安全是基于Lock機制實現的,而Lock的性能往往不如人意。原因是,monitorenter與monitorexit這兩個控制多線程同步的bytecode原語,是JVM依賴操作系統互斥(mutex)來實現的。而互斥是一種會導緻線程挂起,并在較短的時間内又需要重新調度回原線程的,較為消耗資源的操作。所以需要進行對線程進行優化,提高效率。
輕量級鎖
輕量級鎖(LightweightLocking)是從Java6開始引入的概念,本意是為了減少多線程進入互斥的幾率,并不是要替代互斥。它利用了CPU原語Compare-And-Swap(CAS,彙編指令CMPXCHG),嘗試在進入互斥前,進行補救。下面将詳細介紹JVM如何利用CAS,實現輕量級鎖。
JavaObjectModel中定義,ObjectHeader是一個2字(1word=4byte)長度的存儲區域。第一個字長度的區域用來标記同步,GC以及hashcode等,官方稱之為markword。第二個字長度的區域是指向到對象的Class。在2個word中,markword是輕量級鎖實現的關鍵,其結構見右表。
從表中可以看到,state為lightweightlocked的那行即為輕量級鎖标記。bitfieds名為指向lockrecord的指針,這裡的lockrecord,其實是一塊分配在線程堆棧上的空間區域。用于CAS前,拷貝object上的markword。第三項是重量級鎖标記。後面的狀态單詞很有趣,inflated,譯為膨脹,在這裡意思其實是鎖已升級到OS-level。一般我們隻關注第二和第三項即可。lock,unlock與markword之間的聯系如右圖所示。在圖中,提到了拷貝objectmarkword,由于脫離了原始markword,官方将它冠以displaced前綴,即displacedmarkword(置換标記字)。這個displacedmarkword是整個輕量級鎖實現的關鍵,在CAS中的compare就需要用它作為條件。
在拷貝完objectmarkword之後,JVM做了一步交換指針的操作,即流程中第一個橙色矩形框内容所述。将objectmarkword裡的輕量級鎖指針指向lockrecord所在的stack指針,作用是讓其他線程知道,該objectmonitor已被占用。lockrecord裡的owner指針指向objectmarkword的作用是為了在接下裡的運行過程中,識别哪個對象被鎖住了。
最後一步unlock中,我們發現,JVM同樣使用了CAS來驗證objectmarkword在持有鎖到釋放鎖之間,有無被其他線程訪問。如果其他線程在持有鎖這段時間裡,嘗試獲取過鎖,則可能自身被挂起,而markword的重量級鎖指針也會被相應修改。此時,unlock後就需要喚醒被挂起的線程。
偏向鎖
Java偏向鎖(BiasedLocking)是Java6引入的一項多線程優化。它通過消除資源無競争情況下的同步原語,進一步提高了程序的運行性能。它與輕量級鎖的區别在于,輕量級鎖是通過CAS來避免進入開銷較大的互斥操作,而偏向鎖是在無競争場景下完全消除同步,連CAS也不執行(CAS本身仍舊是一種操作系統同步原語,始終要在JVM與OS之間來回,有一定的開銷)。所謂的無競争場景,就是單線程訪問帶同步的資源或方法。
偏向鎖,顧名思義,它會偏向于第一個訪問鎖的線程,如果在接下來的運行過程中,該鎖沒有被其他的線程訪問,則持有偏向鎖的線程将永遠不需要觸發同步。如果在運行過程中,遇到了其他線程搶占鎖,則持有偏向鎖的線程會被挂起,JVM會嘗試消除它身上的偏向鎖,将鎖恢複到标準的輕量級鎖。(偏向鎖隻能在單線程下起作用)。
偏向模式和非偏向模式,在markword表中,主要體現在threadID字段是否為空。
挂起持有偏向鎖的線程,這步操作類似GC的pause,但不同之處是,它隻挂起持有偏向鎖的線程(非當前線程)。
在搶占模式的橙色區域說明中有提到,指向當前堆棧中最近的一個lockrecord(在輕量級鎖中,lockrecord是進入鎖前會在stack上創建的一份内存空間)。這裡提到的最近的一個lockrecord,其實就是當前鎖所在的stackframe上分配的lockrecord。整個步驟是從偏向鎖恢複到輕量級鎖的過程。
偏向鎖也會帶來額外開銷。在JDK6中,偏向鎖是默認啟用的。它提高了單線程訪問同步資源的性能。
但試想一下,如果你的同步資源或代碼一直都是多線程訪問的,那麼消除偏向鎖這一步驟對你來說就是多餘的。事實上,消除偏向鎖的開銷還是蠻大的。所以在你非常熟悉自己的代碼前提下,大可禁用偏向鎖-XX:-UseBiasedLocking。
分類
線程有兩個基本類型:
用戶級線程:管理過程全部由用戶程序完成,操作系統内核心隻對進程進行管理。
系統級線程(核心級線程):由操作系統内核進行管理。操作系統内核給應用程序提供相應的系統調用和應用程序接口API,以使用戶程序可以創建、執行、撤消線程。
舉例UNIXInternational線程
UNIXInternational線程的頭文件是,僅适用于SunSolaris操作系統。所以UNIXInternational線程也常被俗稱為Solaris線程。
1、創建線程
intthr_create(void*stack_base,size_tstack_size,void*(*start_routine)(void*),void*arg,longflags,thread_t*new_thr);
2、等待線程
intthr_join(thread_twait_for,thread_t*dead,void**status);
3、挂起線程
intthr_suspend(thread_tthr);
4、繼續線程
intthr_continue(thread_tthr);
5、退出線程
voidthr_exit(void*status);
6、返回當前線程的線程标識符
thread_tthr_self(void);POSIX線程
POSIX線程(Pthreads)的頭文件是,适用于類Unix操作系統。Windows操作系統并沒有對POSIX線程提供原生的支持庫。不過Win32的POSIX線程庫的一些實現也還是有的,例如pthreads-w32。
1、創建線程
intpthread_create(pthread_t*thread,constpthread_attr_t*attr,void*(*start_routine)(void*),void*arg);
2、等待線程
intpthread_join(pthread_tthread,void**retval);
3、退出線程
voidpthread_exit(void*retval);
4、返回當前線程的線程标識符
pthread_tpthread_self(void);
5、線程取消
intpthread_cancel(pthread_tthread);Win32線程
Win32線程的頭文件是,适用于Windows操作系統。
1、創建線程
HANDLEWINAPICreateThread(LPSECURITY_ATTRIBUTESlpThreadAttributes,SIZE_TdwStackSize,LPTHREAD_START_ROUTINElpStartAddress,LPVOIDlpParameter,DWORDdwCreationFlags,LPDWORDlpThreadId);
2、結束本線程
VOIDWINAPIExitThread(DWORDdwExitCode);
3、挂起指定的線程
DWORDWINAPISuspendThread(HANDLEhThread);
4、恢複指定線程運行
DWORDWINAPIResumeThread(HANDLEhThread);
5、等待線程運行完畢
DWORDWINAPIWaitForSingleObject(HANDLEhHandle,DWORDdwMilliseconds);
6、返回當前線程的線程标識符
DWORDWINAPIGetCurrentThreadId(void);
7、返回當前線程的線程句柄
HANDLEWINAPIGetCurrentThread(void);C++11線程
C++11線程的頭文件是。
創建線程std::thread::thread(Function&&f,Args&&...args);
等待線程結束std::thread::join();
脫離線程控制std::thread::detach();
交換線程std::thread::swap(thread&other);
C11線程
C11線程的頭文件是。
C11線程僅僅是個“建議标準”,也就是說100%遵守C11标準的C編譯器是可以不支持C11線程的。根據C11标準的規定,隻要編譯器預定義了__STDC_NO_THREADS__宏,就可以沒有頭文件,自然也就也沒有下列函數。
1、創建線程
intthrd_create(thrd_t*thr,thrd_start_tfunc,void*arg);
2、結束本線程
_Noreturnvoidthrd_exit(intres);
3、等待線程運行完畢
intthrd_join(thrd_tthr,int*res);
4、返回當前線程的線程标識符
thrd_tthrd_current();Java線程
1、最簡單的情況是,Thread/Runnable的run()方法運行完畢,自行終止。
2、對于更複雜的情況,比如有循環,則可以增加終止标記變量和任務終止的檢查點。
3、最常見的情況,也是為了解決阻塞不能執行檢查點的問題,用中斷來結束線程,但中斷隻是請求,并不能完全保證線程被終止,需要執行線程協同處理。
4、IO阻塞和等鎖情況下需要通過特殊方式進行處理。
5、使用Future類的cancel()方法調用。
6、調用線程池執行器的shutdown()和shutdownNow()方法。
7、守護線程會在非守護線程都結束時自動終止。
8、Thread的stop()方法,但已不推薦使用。
線程的組成
1、一組代表處理器狀态的CPU寄存器中的内容
2、兩個棧,一個用于當線程在内核模式下執行的時候,另一個用于線程在用戶模式下執行的時候
3、一個被稱為線程局部存儲器(TLS,thread-localstorage)的私有儲存區域,各個子系統、運行庫和DLL都會用到該儲存區域
4、一個被稱為線程ID(threadID,線程标識符)的唯一标識符(在内部也被稱為客戶ID——進程ID和線程ID是在同一個名字空間中生産的,所以它們永遠不會重疊)
5、有時候線程也有它們自己的安全環境,如果多線程服務器應用程序要模仿其客戶的安全環境,則往往可以利用線程的安全環境
線程狀态變化
(1)創建線程
當創建一個新的進程時,也創建一個新的線程,進程中的線程可以在同一進程中創建新的線程。
(2)終止線程
可以正常終止自己,也可能某個線程執行錯誤,由其它線程強行終止。終止線程操作主要負責釋放線程占有的寄存器和棧
(3)阻塞線程
當線程等待每個事件無法運行時,停止其運行。
(4)喚醒線程
當阻塞線程的事件發生時,将被阻塞的線程狀态置為就緒态,将其挂到就緒隊列。進程仍然具有與執行相關的狀态。例如,所謂進程處于“執行”狀态,實際上是指該進程中的某線程正在執行。對進程施加的與進程狀态有關的操作,也對其線程起作用。例如,把某個進程挂起時,該進程中的所有線程也都被挂起,激活也是同樣。



















