1. 線程概念的引入背景 1.1 進程 之前我們已經瞭解了操作系統中進程的概念,程式並不能單獨運行,只有將程式裝載到記憶體中,系統為它分配資源才能運行,而這種執行的程式就稱之為進程。程式和進程的區別就在於:程式是指令的集合,它是進程運行的靜態描述文本;進程是程式的一次執行活動,屬於動態概念。在多道編程 ...
1. 線程概念的引入背景
1.1 進程
之前我們已經瞭解了操作系統中進程的概念,程式並不能單獨運行,只有將程式裝載到記憶體中,系統為它分配資源才能運行,而這種執行的程式就稱之為進程。程式和進程的區別就在於:程式是指令的集合,它是進程運行的靜態描述文本;進程是程式的一次執行活動,屬於動態概念。在多道編程中,我們允許多個程式同時載入到記憶體中,在操作系統的調度下,可以實現併發地執行。這是這樣的設計,大大提高了CPU的利用率。進程的出現讓每個用戶感覺到自己獨享CPU,因此,進程就是為了在CPU上實現多道編程而提出的。
1.2 為什麼要有線程
進程有很多優點,它提供了多道編程,讓我們感覺我們每個人都擁有自己的CPU和其他資源,可以提高電腦的利用率。很多人就不理解了,既然進程這麼優秀,為什麼還要線程呢?其實,仔細觀察就會發現進程還是有很多缺陷的,主要體現在兩點上:
進程只能在一個時間乾一件事,如果想同時乾兩件事或多件事,進程就無能為力了。
進程在執行的過程中如果阻塞,例如等待輸入,整個進程就會掛起,即使進程中有些工作不依賴於輸入的數據,也將無法執行。
如果這兩個缺點理解比較困難的話,舉個現實的例子也許你就清楚了:如果把我們上課的過程看成一個進程的話,那麼我們要做的是耳朵聽老師講課,手上還要記筆記,腦子還要思考問題,這樣才能高效的完成聽課的任務。而如果只提供進程這個機制的話,上面這三件事將不能同時執行,同一時間只能做一件事,聽的時候就不能記筆記,也不能用腦子思考,這是其一;如果老師在黑板上寫演算過程,我們開始記筆記,而老師突然有一步推不下去了,阻塞住了,他在那邊思考著,而我們呢,也不能幹其他事,即使你想趁此時思考一下剛纔沒聽懂的一個問題都不行,這是其二。
現在你應該明白了進程的缺陷了,而解決的辦法很簡單,我們完全可以讓聽、寫、思三個獨立的過程,並行起來,這樣很明顯可以提高聽課的效率。而實際的操作系統中,也同樣引入了這種類似的機制——線程。
1.3 線程的出現
60年代,在OS中能擁有資源和獨立運行的基本單位是進程,然而隨著電腦技術的發展,進程出現了很多弊端,一是由於進程是資源擁有者,創建、撤消與切換存在較大的時空開銷,因此需要引入輕型進程;二是由於對稱多處理機(SMP)出現,可以滿足多個運行單位,而多個進程並行開銷過大。 因此在80年代,出現了能獨立運行的基本單位——線程(Threads)。 註意:進程是資源分配的最小單位,線程是CPU調度的最小單位. 每一個進程中至少有一個線程。2. 進程和線程的關係
線程與進程的區別可以歸納為以下4點:
地址空間和其它資源(如打開文件):進程間相互獨立,同一進程的各線程間共用。某進程內的線程在其它進程不可見。 通信:進程間通信IPC,線程間可以直接讀寫進程數據段(如全局變數)來進行通信——需要進程同步和互斥手段的輔助,以保證數據的一致性。 調度和切換:線程上下文切換比進程上下文切換要快得多。 在多線程操作系統中,進程不是一個可執行的實體。
3. 線程的特點
在多線程的操作系統中,通常是在一個進程中包括多個線程,每個線程都是作為利用CPU的基本單位,是花費最小開銷的實體。線程具有以下屬性。
3.1 輕型實體
線程中的實體基本上不擁有系統資源,只是有一點必不可少的、能保證獨立運行的資源。 線程的實體包括程式、數據和TCB。線程是動態概念,它的動態特性由線程式控制制塊TCB(Thread Control Block)描述。TCB包括以下信息:
線程狀態。
當線程不運行時,被保存的現場資源。
一組執行堆棧。
存放每個線程的局部變數主存區。
訪問同一個進程中的主存和其它資源。
用於指示被執行指令序列的程式計數器、保留局部變數、少數狀態參數和返回地址等的一組寄存器和堆棧。
3.2 獨立調度和分派的基本單位
在多線程OS中,線程是能獨立運行的基本單位,因而也是獨立調度和分派的基本單位。由於線程很“輕”,故線程的切換非常迅速且開銷小(在同一進程中的)。
3.3 共用進程資源
線程在同一進程中的各個線程,都可以共用該進程所擁有的資源,這首先表現在:所有線程都具有相同的進程id,這意味著,線程可以訪問該進程的每一個記憶體資源;此外,還可以訪問進程所擁有的已打開文件、定時器、信號量機構等。由於同一個進程內的線程共用記憶體和文件,所以線程之間互相通信不必調用內核。
3.4 可併發執行
在一個進程中的多個線程之間,可以併發執行,甚至允許在一個進程中所有線程都能併發執行;同樣,不同進程中的線程也能併發執行,充分利用和發揮了處理機與外圍設備並行工作的能力。
4. 使用線程的實際場景
開啟一個字處理軟體進程,該進程肯定需要辦不止一件事情,比如監聽鍵盤輸入,處理文字,定時自動將文字保存到硬碟,這三個任務操作的都是同一塊數據,因而不能用多進程。只能在一個進程里併發地開啟三個線程,如果是單線程,那就只能是,鍵盤輸入時,不能處理文字和自動保存,自動保存時又不能輸入和處理文字。
5. 記憶體中的線程
多個線程共用同一個進程的地址空間中的資源,是對一臺電腦上多個進程的模擬,有時也稱線程為輕量級的進程。
而對一臺電腦上多個進程,則共用物理記憶體、磁碟、印表機等其他物理資源。多線程的運行也多進程的運行類似,是cpu在多個線程之間的快速切換。
不同的進程之間是充滿敵意的,彼此是搶占、競爭cpu的關係,如果迅雷會和QQ搶資源。而同一個進程是由一個程式員的程式創建,所以同一進程內的線程是合作關係,一個線程可以訪問另外一個線程的記憶體地址,大家都是共用的,一個線程乾死了另外一個線程的記憶體,那純屬程式員腦子有問題。
類似於進程,每個線程也有自己的堆棧,不同於進程,線程庫無法利用時鐘中斷強制線程讓出CPU,可以調用thread_yield運行線程自動放棄cpu,讓另外一個線程運行。
線程通常是有益的,但是帶來了不小程式設計難度,線程的問題是:
1. 父進程有多個線程,那麼開啟的子線程是否需要同樣多的線程
2. 在同一個進程中,如果一個線程關閉了文件,而另外一個線程正準備往該文件內寫內容呢?
因此,在多線程的代碼中,需要更多的心思來設計程式的邏輯、保護程式的數據。