经典线程同步总结
2019獨角獸企業重金招聘Python工程師標準>>>
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)。不過為什么只有互斥量能解決“遺棄”情況了,請看《秒殺多線程第十五篇 關鍵段,事件,互斥量,信號量的“遺棄”問題》。
轉載于:https://my.oschina.net/u/347414/blog/141614
總結
- 上一篇: python 抓取网页(一)
- 下一篇: xcode4 语法高亮和自动补全失效的解