第二十章 多任務和多線程(線程同步)

線程同步

大約每年一次,在我公寓窗外的交通繁忙地段的紅綠燈會停止工作。結果是造成交通的混亂,雖然轎車一般能避免撞上別的轎車,但是這些車經常擠在一起。

我用術語稱兩條路相交的十字路口爲「臨界區域」。一輛向南的車和一輛向西的車不可能同時通過一個十字路口而不撞着對方。依賴於交通流量,可以採用不同的方法來解決這個問題。對於視野清楚車輛稀少的路口,可以相信司機有處理的能力。車輛增多可能會要求一個停車號誌,而更加繁忙的交通則將要求有紅綠燈,紅綠燈有助於協調路口的交通(當然,這些燈號必須正常工作)。

臨界區域

在單工操作系統中,傳統的計算機程序不需要紅綠燈來幫助協調它們之間的行爲。它們在執行時似乎獨佔了整條路,而且也確實是這樣,沒有什麼會干擾它們的工作。

即使在多任務操作系統中,大多數的程序也似乎各自獨立地在執行,但是可能會發生一些問題。例如,兩個程序可能會需要同時從同一個文件中讀或者對同一文件進行寫。在這種情況下,操作系統提供了一種共享文件和記錄上鎖的技術來幫助解決這個問題。

然而,在支持多線程的操作系統中,情況會變得混亂而且存在潛在的危險。兩個或多個線程共享某些數據的情況並不罕見。例如,一個線程可以更新一個或者多個變量,而另一個線程可以使用這些變量。有時這會引發一個問題,有時又不會(記住操作系統將控制權從一個線程切換到另一個線程的操作,只能在機器碼指令之間發生。如果只是一個整數被線程共享,那麼對這個變量的改變通常發生在單個指令中,因此潛在的問題被最小化了)。

然而,假設線程共享幾個變量或者數據結構。通常,這麼多個變量或者結構的字段在它們之間必須是一致的。操作系統可以在更新這些變量的程序中間中斷一個線程,那麼使用這些變量的線程得到的將是不一致的數據。

結果是衝突發生了,並且通常不難想象這樣的錯誤將對程序造成怎樣的破壞。我們所需要的是類似於紅綠燈的程序寫作技術,以幫助我們對線程交通進行協調和同步,這就是臨界區域。大體上,一個臨界區域就是一塊不可中斷的程序代碼。

有四個函數用於臨界區域。要使用這些函數,您必須定義一個臨界區域對象,這是一個型態爲CRITICAL_SECTION的整體變量。例如:

CRITICAL_SECTION cs ;

這個CRITICAL_SECTION數據型態是一個結構,但是其中的字段只能由Windows內部使用。這個臨界區域對象必須先被程序中的某個線程初始化,通過呼叫:

InitializeCriticalSection (&cs) ;

這樣就建立了一個名爲cs的臨界區域對象。該函數的在線輔助說明包含下面的警告:「臨界區域對象不能被移動或者複製,程序也不能修改該對象,但必須在邏輯上把它視爲不透明的。」這句話,可以被解釋爲:「不要干擾它,甚至不要看它。」

當臨界區域對象被初始化之後,線程可以通過下面的呼叫進入臨界區域:

EnterCriticalSection (&cs) ;

在這時,線程被認爲「擁有」臨界區域對象。兩個線程不可以同時擁有同一個臨界區域對象,因此,如果一個線程進入了臨界區域,那麼下一個使用同一臨界區域對象呼叫EnterCriticalSection的線程將在函數呼叫中被暫停。只有當第一個線程通過下面的呼叫離開臨界區域時,函數纔會傳回控制權:

LeaveCriticalSection (&cs) ;

這時,在EnterCriticalSection呼叫中被停住的那個線程將擁有臨界區域,其函數呼叫也將傳回,允許線程繼續執行。

當臨界區域不再被程序所需要時,可以通過呼叫

DeleteCriticalSection (&cs) ;

將其刪除,該函數釋放所有被配置來維護此臨界區域對象的系統資源。

這種臨界區域技術涉及「互斥」(此術語在我們繼續討論線程同步時將再次出現)。在任何時刻,只有一個線程能擁有一個臨界區域。因此,一個線程可以進入一個臨界區域,設定一個結構的字段,然後退出臨界區域。另一個使用該結構的線程在存取結構中的字段之前也要先進入該臨界區域,然後再退出臨界區域。

注意,您可以定義多個臨界區域對象,比如cs1和cs2。例如,如果一個程序有四個線程,而前兩個線程共享一些數據,那麼它們可以使用一個臨界區域對象,而另外兩個線程共享一些其它的數據,那麼它們可以使用另一個臨界區域對象。

您在主線程中使用臨界區域時應該小心。如果從屬線程在它自己的臨界區域中花費了一段很長的時間,那麼它可能會將主線程的執行阻礙很長一段時間。從屬執行緒可能只是使用臨界區域複製該結構的字段到自己的區域變量中。

臨界區域的一個限制是它們只能用於在同一程序內的線程之間的協調。但是在某些情況下,您需要協調兩個不同程序對同一資源的共享(如共享內存等)。在此其況下不能使用臨界區域,但是可以使用一種被稱爲「互斥對象(mutex object)」的技術。「mutex」是個合成字,代表「mutual exclusion(互斥)」,它在這裏精確地表達了我們的目的。我們想防止一個程序的線程在更新數據或者使用共享內存與其它資源時被中斷。

 

==================================================

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章