1. 程式人生 > >C#程式設計 執行緒,任務和同步(1) 基礎認識

C#程式設計 執行緒,任務和同步(1) 基礎認識

執行緒

對於所有需要等待的操作,例如移動檔案,資料庫和網路訪問都需要一定的時間,此時就可以啟動一個新的執行緒,同時完成其他任務。一個程序的多個執行緒可以同時執行在不同的CPU上或多核CPU的不同核心上。

執行緒是程式中獨立的指令流。在VS編輯器中輸入程式碼的時候,系統會分析程式碼,用下劃線標註遺漏的分號和其他語法錯誤,這就是用一個後臺執行緒完成。Word文件需要一個執行緒等待使用者輸入,另一個執行緒進行後臺搜尋,第三個執行緒將寫入的資料儲存在臨時檔案中。執行在伺服器上的應用程式中等待客戶請求的執行緒成為偵聽器執行緒。

程序包含資源,如Window控制代碼,檔案系統控制代碼或其他核心物件。每個程序都分配的虛擬記憶體。一個程序至少包含一個執行緒。

一個應用程式啟動,一般會啟動一個程序,然後程序啟動多個執行緒。

程序和執行緒的一個簡單解釋

1,計算機的核心是CPU,它承擔了所有的計算任務。它就像一座工廠,時刻在執行。

2,如果工廠的電力有限一次只能供給一個車間使用。也就是說一個車間開工的時候,其他車間就必須停工。背後的含義就是。單個CPU一次只能執行一個任務。(多核CPU可以執行多個任務)  

3,程序就好比工廠的車間,它代表CPU所能處理的單個任務。任一時刻,CPU總是執行一個程序,其他程序處於非執行狀態。

4,一個車間裡,可以有很多工人,他們協同完成一個任務。

5,執行緒就好比車間裡的工人。一個程序可以包括多個執行緒。

6,車間的控制元件是工人們共享的,比如許多房間是每個工人都可以進出的。這象徵一個程序的記憶體空間是共享的,每個執行緒都可以使用這些共享空間。

7,程序就好比工廠的車間,它代表CPU所能處理的單個任務。任一時刻,CPU總是執行一個程序,其他程序處於非執行狀態。

8,一個防止他人進入的簡單方法,就是門口加一把鎖(廁所)。先到的人鎖上門,後到的人看到上鎖,就在門口排隊,等鎖開啟再進去。這就叫"互斥鎖"(Mutual exclusion,縮寫 Mutex),防止多個執行緒同時讀寫某一塊記憶體區域。

9,還有些房間,可以同時容納n個人,比如廚房。也就是說,如果人數大於n,多出來的人只能在外面等著。這好比某些記憶體區域,只能供給固定數目的執行緒使用。

10,這時的解決方法,就是在門口掛n把鑰匙。進去的人就取一把鑰匙,出來時再把鑰匙掛回原處。後到的人發現鑰匙架空了,就知道必須在門口排隊等著了。這種做法叫做"訊號量"(Semaphore),用來保證多個執行緒不會互相沖突。 不難看出,mutex是semaphore的一種特殊情況(n=1時)。也就是說,完全可以用後者替代前者。但是,因為mutex較為簡單,且效率高,所以在必須保證資源獨佔的情況下,還是採用這種設計。

11,作業系統的設計,因此可以歸結為三點:

(1)以多程序形式,允許多個任務同時執行;

(2)以多執行緒形式,允許單個任務分成不同的部分執行;

(3)提供協調機制,一方面防止程序之間和執行緒之間產生衝突,另一方面允許程序之間和執行緒之間共享資源。

 

後臺執行緒和前臺執行緒

只有一個前臺執行緒在執行,應用程式的程序就在執行,如果多個前臺執行緒在執行,但是Main方法結束了,應用程式的程序仍然是執行的,直到所有的前臺執行緒完成其任務為止。

在預設情況下,用Thread類建立的執行緒是前臺執行緒。執行緒池中的執行緒總是後臺執行緒。

在用Thread類建立執行緒的時候,可以設定IsBackground屬性,表示它是一個前臺執行緒還是一個後臺執行緒。

後臺執行緒用的地方:如果關閉Word應用程式,拼寫檢查器繼續執行就沒有意義了,在關閉應用程式的時候,拼寫檢查執行緒就可以關閉。

當所有的前臺執行緒執行完畢,如果還有後臺執行緒執行的話,所有的後臺執行緒會被終止掉。

 

執行緒的優先順序

執行緒有作業系統排程,一個CPU同一時間只能做一件事情(執行一個執行緒中的計算任務),當有很多執行緒需要CPU去執行的時候,執行緒排程器會根據執行緒的優先順序去判斷先去執行哪一個執行緒,如果優先順序相同的話,就使用一個迴圈排程規則,逐個執行每個執行緒。

在Thead類中,可以設定Priority屬性,以影響執行緒的基本優先順序 ,Priority屬性是一個ThreadPriority列舉定義的一個值。定義的級別有Highest ,AboveNormal,BelowNormal 和 Lowest。

 

控制執行緒

1,獲取執行緒的狀態(Running還是Unstarted,,,),當我們通過呼叫Thread物件的Start方法,可以建立執行緒,但是呼叫了Start方法之後,新執行緒不是馬上進入Running狀態,而是出於Unstarted狀態,只有當作業系統的執行緒排程器選擇了要執行的執行緒,這個執行緒的狀態才會修改為Running狀態。我們使用Thread.Sleep()方法可以讓當前執行緒休眠進入WaitSleepJoin狀態。

2,使用Thread物件的Abort()方法可以停止執行緒。呼叫這個方法,會在終止要終止的執行緒中丟擲一個ThreadAbortException型別的異常,我們可以try catch這個異常,然後線上程結束前做一些清理的工作。

3,如果需要等待執行緒的結束,可以呼叫Thread物件的Join方法,表示把Thread加入進來,停止當前執行緒,並把它設定為WaitSleepJoin狀態,直到加入的執行緒完成為止。