在你很小的時候,你學習怎樣一次完成一個工作,但到了成年,當然也許你已成為父母輩了,這時,你就必須學會如何在同一時間做多個工作。例如,你是否發現有多少次你在辦公室裡作弄過電話,E-MAIL 和客人?你也許正在辦公室裡和一個人在談話,這時電話鈴響了,談話就被電話打斷了。也許正在打電話時,你又來了新(重要的)E-MAIL,你必須中斷你的電話。一旦處理完E-MAIL以後,你可以接著打電話或者繼續和辦公室裡的人談話。如果等的時間太長了,電話另一端的人可能會掛斷電話,或者辦公室裡的人也許會生氣離開。你必須決定如何花費你的時間和花在誰身上。
在上面的例子中,你就是在進行多任務處理。你決定如何花費你的時間和電腦對多任務進行時序安排類似。正如我們一天只有24小時,電腦的資源也是有限的。看起來好像你在同時打電話和處理E-MAIL,但事實上,每次你只能將注意力集中在一件事情上。實際上你是在不斷變換注意力,只不過變換得足夠快,就好像你在同時做多個工作一樣。當電腦處理多任務時,它從一個程式到另一個程式的切換是非常快的,以至於使你認為,所有 的程式都在同時運行。
圖一,從使用者觀點看單任務和多任務
假如你有一個複製(可能叫多莉)的話,你就能同時做兩件事。對於有多個CPU的電腦,同時在每一個CPU上運行程式稱為多重處理。有時,人們可替換使用多任務處理和多重處理兩個概念,但是,你不能在沒有多個處理器的電腦上進行多重處理。因此,如果你正在使用一台只有一個處理器的電腦,作業系統可以進行多任務處理,如果你正在使用一台有多個處理器的電腦,作業系統既能進行多任務處理又能進行多重處理。
在作業系統中,過程是一個邏輯上的任務。過程是在運行應用程式,啟動某一系統服務,和在Windows NT中啟動某一子系統時產生的。每一個過程都有自己的專用資源(例如自己的專用儲存空間),只有擁有這個過程的應用程式才能訪問這些資源。這意味著,如果你產生了一個程式,在程式中用到一些資料,並且你也沒有建立任何形式的程式間資料共用機制或使用作業系統的程式間資料共用機制,那麼就只有你的程式能訪問這些資料。大多數Windows開發人員都用COM對象簡化程式間的通訊。如果你用的是Windows NT並且想共用資料,你可以使用記憶體映像檔案。但是這對於Geek Speak column來說技術性太強,所以讓我們繼續往下講。
多任務處理:合作的和有優先權的
你能使用的多任務處理有兩種基本方法:合作的,在這種方法中,正在啟動並執行過程必須為其他過程留出CPU時間片;有優先權的,在這種方法中,作業系統決定哪個程式獲得時間片。Microsoft Windows 3.x和Macintosh用的都是合作的多任務處理,而OS/2,Windows 95,Windows NT,UNIX,和Amiga作業系統使用的是有優先權的多任務處理。
合作的多任務處理
如果使用合作的多任務處理,每個程式必須允許其他程式使用CPU。使用合作的多任務處理系統的應用軟體都有一個特殊的碼環,這個碼環產生控制允許其他應用軟體的運行。如果每個人都按規則辦事,這種方法會工作得相當好,但是當應用程式不服從這一規則時,他“霸佔”CPU。這意味著,終端使用者不能轉向其他應用程式,使作業系統或應用程式出現“掛起”。
有優先權的多任務處理
在有優先權的多任務處理中,作業系統安排CPU時間,一個應用軟體在任何時候都有可能被作業系統暫停(先佔)。這減輕了“一玩到底”的程式問題,因為作業系統負責分給每個應用軟體自己的時間片。
Windows 95對於32位Windows應用程式採用有優先權的多任務處理,為了能夠向下相容,對於16位的Windows應用程式(為Windows 3.x寫的應用程式)仍採用合作的多任務處理。
線程
線程是一個能獨立於程式的其他部分啟動並執行作業。線程屬於一個過程,獲得自己的CPU時間片。基於WIN32的應用程式可以使用多個可執行檔線程,稱為多線程。Windows 3.x不能提供一種機制天然地支援多線程應用程式,但是一些為Windows 3.x編寫應用程式的公司使用他們自己的線程安排。
基於WIN32的應用軟體能在給定的過程中產生多個線程。依靠產生多個線程,應用程式能夠完成一些後台操作,例如計算,這樣程式就能運行得更快。當線程運行時,使用者仍能繼續影響程式。正如前面談到的,當一個應用程式運行時,就產生了一個相應的過程。那麼應用程式就能有一個單獨的線程等待鍵盤輸入或執行一個操作,例如離線列印或計算試算表中各項的總數。
在網路世界中,當你試圖調整你網站的伺服器的效能時,就要運行線程。如果你使用的是IIS,你可以在伺服器上設定對於每個處理器所能建立的線程的最大數目。這樣,就能在處理器間更均勻地分配工作,從而加速你的網站。
線程模式
現在,為了讓你知道線程是什麼和在哪能使用他們,讓我們看一下使用線程時你可能要啟動並執行應用程式:ActiveX組件。ActiveX組件是獨立於其他代碼運行,基於COM的代碼。這聽起來是不是很熟悉?當你使用ActiveX組件時,必須在作業系統中註冊。其中的一條註冊資訊就是,這個ActiveX組件是否支援多個線程,如果支援怎樣支援。這就是線程模式。
組件支援的基本線程模式有:單線程,單元線程,組合線程。下面幾個部分將談談每一種模式對組件來說意味著什麼。
單線程
如果組件被標記(即註冊)為單執行緒元件,這就意味著所有可執行函數(稱作方法)都將在組件的一個共用線程中運行。這就類似於沒有產生獨立的可執行線程的應用程式。單執行緒元件的缺點是一次只能運行一個方法。如果多次調用組件,例如調用組件中的儲存方法,就會產生瓶頸,因為一次只能有一個調用。
如果你正在建立或使用一個ActiveX組件,建議不要使用單執行緒元件。
單元線程
如果一個組件被標記為單元線程,那麼每個可執行檔方法都將在一個和組件相聯絡的線程上運行。之所以成為單元線程是因為,每個新產生的組件執行個體都有一個相應的線程單元,每個正在啟動並執行組件都有它自己的線程。Apartment 執行緒元件要比單執行緒元件要好,因為多個組件可以在各自的單元中同時運行方法。
自由線程
一個自由執行緒元件是一個支援多執行緒 Apartment的多執行緒元件。這意味著多個方法調用可同時運行,因為每個調用都有自己的運行線程。這能使你的組件運行快得多,但也有一些缺點。運行在同一單元中的單元組件可以在單元中直接調用其他組件的方法,這是一個非常快的操作。但是,自由執行緒元件必須從一個單元向另一個單元調用。為了實現這一操作,WIN32產生了一個代理,用來通過單元界線。這對於每個需要的功能調用來說就產生了系統開銷,從而減低了系統的速度。每一個訪問自由組件的調用都有一個相應的代理。既然代理調用比直接調用慢,那麼自然會有效能方面的降低。
關於自由執行緒元件另一個需要注意的是:他們不是真正自由的。如果你建立了一個自由執行緒元件。你仍必須確保組件中的線程完全同步。這不是一件容易的事。只是簡單地把你的組件標記為是自由線程的,並不能使你的組件支援多線程,你仍要去做使你的組件自由線程化的工作。如果你不做這個工作,你的共用資料可能被破壞。這裡說明一下為什麼:讓我們假定你有一個方法計算某個數然後把它寫到某個變數中。此方法被傳入一個初始值例如是4,在隨後的計算中這個變數的值增長為5。在方法結束時這個最後的值被寫入到變數中。如果一次只有一個計算過程的話,所有這些會工作得很好。然而,當資料正在被改變時,另一個線程試圖訪問它,那麼重新得到的資料就有可能是錯誤的。下面的圖表說明了這一點。
為了修正這一錯誤,開發人員為對象提供了線程同步。線程同步是在正在運行你想保護的某一其他代碼時啟動並執行代碼。作業系統並不先佔這個代碼,直到獲得一個可以中斷的訊號。如果你想瞭解更多的有關線程同步對象的詳細內容,你不應該閱讀Geek Speak column!不,我的意思是,“注意看一下本文後面列出的參考閱讀文獻”。
圖二,共用資料被多線程訪問搞亂了
組合線程
讀到這,你也許會想既然每種形式的線程都有自己的優點和缺點,為什麼不把不同的線程模式結合起來使用呢?組合線程模式也許符合你的要求。一個被標記為組合線程的組件既有Apartment 執行緒元件的特性又有自由執行緒元件的特性。當一個組件被標記為組合線程時,這個組件將總是在和產生它的對象所在單元相同的單元中建立。如果組件是被一個標記為單線程的對象建立的,那麼這個組件的行為將和一個Apartment 執行緒元件一樣,並且它將線上程單元中建立。這就意味著,組件和建立它的對象之間的調用,不需要一個為通訊提供的代理調用。
如果新組件是被自由執行緒元件建立的,那麼這個組件將表現得像一個自由執行緒元件,但是它將在同一單元中運行,因此新組件能夠直接存取建立它的對象(既不需代理調用)。切記,如果你打算把你的組件標記為組合線程,你必須提供線程同步保護你的線程資料。
更多的資訊
到此為止,你應該對過程,作業,線程有一個基本的瞭解了。如果你想進一步瞭解,下面這些文章也許對你有用。我必須事先提醒你,這些資料中的大多數並不是為初學者準備的。很好地理解COM,C++,和WIN32,將會對理解某些文章大有協助。
- Multithreading for Rookies ( http://msdn.microsoft.com/library/techart/msdn_threads.htm) by Ruediger Asche
- Windows 95 Resource Kit, Chapter 31 The Windows 95 Architecture, Virtual Machine Manager, Process Scheduling and Multitasking ( http://msdn.microsoft.com/library/winresource/dnwin95/d1c/s72bd.htm)
- Understanding and Using COM Threading Models ( http://www.microsoft.com/workshop/components/com/comthread.asp)
- Descriptions and Workings of OLE Threading Models ( http://support.microsoft.com/support/kb/articles/q150/7/77.asp)
- Fashionable App Designers Agree: The Free-Threading Model is What抯 Hot This Fall ( http://www.microsoft.com/msj/0897/free.htm)
- IIS Documentation: Selecting a Threading Mode ( http://msdn.microsoft.com/library/sdkdoc/iisref/eadg2pbg.htm)