1、解釋python
線程之間通訊的兩個基本問題是互斥和同步。windows
線程同步是指:線程之間所具備的一種制約關係,一個線程的執行依賴另外一個線程的消息,當它沒有獲得另外一個線程的消息時,應該等待,直到消息到達時才被喚醒。多線程
線程互斥是指:對於共享的操做系統資源(指的是廣義的「資源」,而不是Windows.res文件,譬如全局變量就是一種共享資源),在各線程訪問時的排它性。當有若干個線程都要使用某一共享資源時,任什麼時候刻最多隻容許一個線程去使用,其餘要使用該資源的線程必須等待,直到佔用資源者釋放該資源。ide
線程互斥是一種特殊的線程同步。函數
實際上,互斥和同步對應着線程間通訊發生的兩種狀況:性能
(1) 當有多個線程訪問共享資源而不使資源被破壞時;spa
(2) 當一個線程須要將某個任務已經完成的狀況通知另外一個或多個線程時。操作系統
2、在windows32中,同步機制主要有如下幾種:線程
(1) 事件(Event);3d
(2)信號量(semaphore);
(3)互斥量(mutex);
(4)臨界區(Critical, section)
全局變量
由於進程中的全部線程都可以訪問全部的全局變量,於是全局變量成爲Win32多線程通訊的最簡單方式。
事件
事件(Event)是WIN32提供的最靈活的線程間同步方式,事件能夠處於激發狀態(signaled or true) 或未激發狀態(unsignal or False)。根據狀態變遷方式的不一樣,事件可分爲兩類:
(1) 手動設置:這種對象只可能用程序手動設置,在須要該事件或者事件發生時,採用SetEvent及ResetEvent來進行設置。
(2) 自動恢復: 一旦事件發生並被處理後,自動恢復到沒有事件狀態,不須要再次設置。
例子:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import threading 5 import time 6 7 8 def func(): 9 # 線程之間的通訊,能夠用事件去實現 10 # 建立一個事件對象 11 event = threading.Event() 12 13 def run(): 14 for i in range(5): 15 # wait:阻塞,等待事件的觸發 16 event.wait() 17 # clear(): 重置,使上面的wait重置到阻塞狀態。 18 event.clear() 19 print('sunck is a good man! %d' % i) 20 21 t = threading.Thread(target=run).start() 22 return event 23 24 25 e = func() 26 # 觸發事件 27 for i in range(5): 28 time.sleep(2) 29 # 設置事件 30 e.set()
使用「事件」機制應該注意如下事項:
(1) 若是跨進程訪問事件,必須對事件命名,在對事件命名的時候,要注意不要與系統命名空間中的其它全局命名對象衝突;
(2) 事件是否要自動恢復;
(3) 事件的初始狀態設置。
因爲event對象屬於內核對象,故進程B能夠調用OpenEvent函數經過對象的名字得到進程A中event對象的句柄,而後將這個句柄用於ResetEvent、SetEvent和WaitForMultipleObjects等函數中。此法能夠實現一個進程的線程控制另外一進程中線程的運行。
臨界區
定義臨界區變量
一般狀況下,CRITICAL_SECTION結構體應該被定義爲全局變量,以便於進程中的全部線程方便地按照變量名來引用該結構體。
關於臨界區的使用,有下列注意點:
(1)每一個共享資源使用一個CRITICAL_SECTION變量;
(2)不要長時間運行關鍵代碼段,當一個關鍵代碼段長時間運行時,其餘線程就會進入等待狀態,這會下降應用程序的運行性能;
(3)若是須要同時訪問多個資源,則可能連續調用EnterCriticalSection;
(4)Critical Section不是OS核心對象,若是進入臨界區的線程"掛"了,將沒法釋放臨界資源。這個缺點在Mutex中獲得了彌補。
互斥
互斥量的做用是保證每次只能有一個線程得到互斥量而得以繼續執行,使用CreateMutex函數建立,Mutex是核心對象,能夠跨進程訪問。
互斥(mutex)內核對象可以確保線程擁有對單個資源的互斥訪問權。互斥對象的行爲特性與臨界區相同,可是互斥對象屬於內核對象,而臨界區則屬於用戶方式對象,所以這致使mutex與Critical Section的以下不一樣: (1) 互斥對象的運行速度比關鍵代碼段要慢; (2) 不一樣進程中的多個線程可以訪問單個互斥對象; (3) 線程在等待訪問資源時能夠設定一個超時值。