前面《秒殺多線程第四篇一個經典的多線程同步問題》提出了一個經典的多線程同步互斥問題,這個問題包括了主線程與子線程的同步,子線程間的互斥,是一道非常經典的多線程同步互斥問題範例,後面分別用了四篇
來詳細介紹常用的線程同步互斥機制——關鍵段、事件、互斥量、信號量。下面對它們作個總結,幫助大家梳理各個知識點。
首先來看下關於線程同步互斥的概念性的知識,相信大家通過前面的文章,已經對線程同步互斥有一定的認識了,也能模糊的說出線程同步互斥的各種概念性知識,下面再列出從《計算機操作系統》一書中選取的一些關於線程同步互斥的描述。相信先有個初步而模糊的印象再看下權威的定義,應該會記憶的特別深刻。
1.線程(進程)同步的主要任務
答:在引入多線程後,由於線程執行的異步性,會給系統造成混亂,特別是在急用臨界資源時,如多個線程急用同一臺打印機,會使打印結果交織在一起,難於區分。當多個線程急用共享變量,表格,鏈表時,可能會導致數據處理出錯,因此線程同步的主要任務是使併發執行的各線程之間能夠有效的共享資源和相互合作,從而使程序的執行具有可再現性。
2.線程(進程)之間的制約關係?
當線程併發執行時,由於資源共享和線程協作,使用線程之間會存在以下兩種制約關係。
(1).間接相互制約。一個系統中的多個線程必然要共享某種系統資源,如共享CPU,共享I/O設備,所謂間接相互制約即源於這種資源共享,打印機就是最好的例子,線程A在使用打印機時,其它線程都要等待。
(2).直接相互制約。這種制約主要是因爲線程之間的合作,如有線程A將計算結果提供給線程B作進一步處理,那麼線程B在線程A將數據送達之前都將處於阻塞狀態。
間接相互制約可以稱爲互斥,直接相互制約可以稱爲同步,對於互斥可以這樣理解,線程A和線程B互斥訪問某個資源則它們之間就會產個順序問題——要麼線程A等待線程B操作完畢,要麼線程B等待線程操作完畢,這其實就是線程的同步了。因此同步包括互斥,互斥其實是一種特殊的同步。
3.臨界資源和臨界區
在一段時間內只允許一個線程訪問的資源就稱爲臨界資源或獨佔資源,計算機中大多數物理設備,進程中的共享變量等待都是臨界資源,它們要求被互斥的訪問。每個進程中訪問臨界資源的代碼稱爲臨界區
看完概念性知識,下面用幾個表格來幫助大家更好的記憶和運用多線程同步互斥的四個實現方法——關鍵段、事件、互斥量、信號量。
關鍵段CS與互斥量Mutex
|
創建或初始化 |
銷燬 |
進入互斥區域 |
離開互斥區域 |
關鍵段CS |
Initialize- CriticalSection |
Delete- CriticalSection |
Enter- CriticalSection |
Leave- CriticalSection |
互斥量Mutex |
CreateMutex |
CloseHandle |
等待系列函數如WaitForSingleObject |
ReleaseMutex |
關鍵段與互斥量都有“線程所有權”概念,可以將“線程所有權”理解成旅館的房卡,在旅館前臺登記名字擁有房卡後是可以多次進出房間的,其它人則無法進入直到你交出房卡。每個線程必須先通過EnterCriticalSection或WaitForSingleObject來嘗試獲得“線程所有權”才能調用LeaveCriticalSection或ReleaseMutex。否則會調用失敗,這就相當於僞造房卡去辦理退房手續——由於登記本上沒有你的名字所以會被拒絕。
互斥量能很好的處理“遺棄”情況,因此在多進程之間可以放心的使用。
事件Event
|
創建 |
銷燬 |
使事件觸發 |
使事件未觸發 |
事件Event |
CreateEvent |
CloseHandle |
SetEvent |
ResetEvent |
注意事件的手動置位和自動置位要分清楚,不要混淆了。
信號量Semaphore
|
創建 |
銷燬 |
遞減計數 |
遞增計數 |
信號量 Semaphore |
Create- Semaphore |
CloseHandle |
等待系列函數如WaitForSingleObject |
Release- Semaphore |
信號量在計數大於0時表示觸發狀態,調用WaitForSingleObject不會阻塞,等於0表示未觸發狀態,調用WaitForSingleObject會阻塞直到有其它線程遞增了計數。
注意:互斥量,事件,信號量都是內核對象,可以跨進程使用(通過OpenMutex,OpenEvent,OpenSemaphore)。不過爲什麼只有互斥量能解決“遺棄”情況了,請看《秒殺多線程第十五篇 關鍵段,事件,互斥量,信號量的“遺棄”問題》。
呵呵^_^,本系列一共使用了六篇文章來講解了上面三個表格,如果讀者能輕鬆寫出這個表格並能解釋下各函數的用法,那麼對多線程的同步互斥問題也就有了良好的基礎。
通過經典線程同步問題的學習,我們已經初步練好了解決多線程同步互斥的各種“招式”,下面再通過學習二個著名的實例《秒殺多線程第十篇 生產者消費者問題》和《秒殺多線程第十一篇 讀者寫者問題》來使我們在解決多線程同步時更加熟練。
轉載請標明出處,原文地址:http://blog.csdn.net/morewindows/article/details/7538247