1.線程(進程)同步的主要任務 windows
答:在引入多線程後,因爲線程執行的異步性,會給系統形成混亂,特別是在急用臨界資源時,如多個線程急用同一臺打印機,會使打印結果交織在一塊兒,難於區分。當多個線程急用共享變量,表格,鏈表時,可能會致使數據處理出錯,所以線程同步的主要任務是使併發執行的各線程之間可以有效的共享資源和相互合做,從而使程序的執行具備可再現性。 多線程
2.線程(進程)之間的制約關係? 併發
當線程併發執行時,因爲資源共享和線程協做,使用線程之間會存在如下兩種制約關係。 異步
(1)間接相互制約。一個系統中的多個線程必然要共享某種系統資源,如共享CPU,共享I/O設備,所謂間接相互制約即源於這種資源共享,打印機就是最好的例子,線程A在使用打印機時,其它線程都要等待。 函數
(2)直接相互制約。這種制約主要是由於線程之間的合做,若有線程A將計算結果提供給線程B做進一步處理,那麼線程B在線程A將數據送達以前都將處於阻塞狀態。 spa
間接相互制約能夠稱爲互斥,直接相互制約能夠稱爲同步,對於互斥能夠這樣理解,線程A和線程B互斥訪問某個資源則它們之間就會產個順序問題——要麼線程A等待線程B操做完畢,要麼線程B等待線程操做完畢,這其實就是線程的同步了。所以同步包括互斥,互斥實際上是一種特殊的同步。 .net
3.臨界資源和臨界區 線程
在一段時間內只容許一個線程訪問的資源就稱爲臨界資源或獨佔資源,計算機中大多數物理設備,進程中的共享變量等待都是臨界資源,它們要求被互斥的訪問。每一個進程中訪問臨界資源的代碼稱爲臨界區 對象
看完概念性知識,下面用幾個表格來幫助你們更好的記憶和運用多線程同步互斥的四個實現方法——關鍵段、事件、互斥量、信號量。 blog
關鍵段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)。不過爲何只有互斥量能解決「遺棄」狀況了,請看《秒殺多線程第十五篇 關鍵段,事件,互斥量,信號量的「遺棄」問題》。