Windows多線程編程主要涉及的四個對象分別是:關鍵段CS,互斥量Mutex,信號量Semaphore ,事件Event 。其中多線程間互斥訪問主要使用關鍵段CS,互斥量Mutex完成。多線程間的同步使用信號量Semaphore ,事件Event來完成。編程
關鍵段CS與互斥量Mutex都是完成多線程間的互斥,可是二者的區別是:互斥量能夠完成不一樣進程的線程間的對資源的互斥訪問。而關鍵段CS只可以完成同一進程的不一樣線程間的互斥。並且互斥量能完成對於線程訪問互斥資源而異常退出沒有釋放互斥鎖的狀況。數組
信號量Semaphore 與事件Event都能完成線程間的同步,可是信號量Semaphore是每次觸發加1,每次執行減1,若是信號量爲0就不在執行了。而事件Event只要設置了事件爲執行狀態,只要不設置事件爲退出狀態,監聽這一事件的全部線程都會執行。安全
關鍵段CS介紹和使用:多線程
關鍵段CRITICAL_SECTION一共就四個函數,使用非常方便。下面是這四個函數的原型和使用說明。併發
函數功能:初始化ide
函數原型:函數
void InitializeCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);spa
函數說明:定義關鍵段變量後必須先初始化。線程
函數功能:銷燬對象
函數原型:
void DeleteCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);
函數說明:用完以後記得銷燬。
函數功能:進入關鍵區域
函數原型:
void EnterCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);
函數說明:系統保證各線程互斥的進入關鍵區域。
函數功能:離開關關鍵區域
函數原型:
void LeaveCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);
互斥量Mutex介紹和使用:
第一個CreateMutex
函數功能:建立互斥量(注意與事件Event的建立函數對比)
函數原型:
HANDLECreateMutex(
LPSECURITY_ATTRIBUTESlpMutexAttributes,
BOOLbInitialOwner,
LPCTSTRlpName
);
函數說明:
第一個參數表示安全控制,通常直接傳入NULL。
第二個參數用來肯定互斥量的初始擁有者。若是傳入TRUE表示互斥量對象內部會記錄建立它的線程的線程ID號並將遞歸計數設置爲1,因爲該線程ID非零,因此互斥量處於未觸發狀態。若是傳入FALSE,那麼互斥量對象內部的線程ID號將設置爲NULL,遞歸計數設置爲0,這意味互斥量不爲任何線程佔用,處於觸發狀態。
第三個參數用來設置互斥量的名稱,在多個進程中的線程就是經過名稱來確保它們訪問的是同一個互斥量。
函數訪問值:
成功返回一個表示互斥量的句柄,失敗返回NULL。
第二個打開互斥量
函數原型:
HANDLEOpenMutex(
DWORDdwDesiredAccess,
BOOLbInheritHandle,
LPCTSTRlpName //名稱
);
函數說明:
第一個參數表示訪問權限,對互斥量通常傳入MUTEX_ALL_ACCESS。詳細解釋能夠查看MSDN文檔。
第二個參數表示互斥量句柄繼承性,通常傳入TRUE便可。
第三個參數表示名稱。某一個進程中的線程建立互斥量後,其它進程中的線程就能夠經過這個函數來找到這個互斥量。
函數訪問值:
成功返回一個表示互斥量的句柄,失敗返回NULL。
第三個觸發互斥量
函數原型:
BOOLReleaseMutex (HANDLEhMutex)
函數說明:
訪問互斥資源前應該要調用等待函數,結束訪問時就要調用ReleaseMutex()來表示本身已經結束訪問,其它線程能夠開始訪問了。
最後一個清理互斥量
因爲互斥量是內核對象,所以使用CloseHandle()就能夠
ReleaseMutex()觸發互斥量前就意外終止了(至關於該互斥量被「遺棄」了),那麼全部等待這個互斥量的線程是否會因爲該互斥量沒法被觸發而陷入一個無窮的等待過程當中了?這顯然不合理。由於佔用某個互斥量的線程既然終止了那足以證實它再也不使用被該互斥量保護的資源,因此這些資源徹底而且應當被其它線程來使用。所以在這種「遺棄」狀況下,系統自動把該互斥量內部的線程ID設置爲0,並將它的遞歸計數器復置爲0,表示這個互斥量被觸發了。而後系統將「公平地」選定一個等待線程來完成調度(被選中的線程的WaitForSingleObject()會返回WAIT_ABANDONED_0)。
信號量Semaphore 的介紹和使用
抽象的來說,信號量的特性以下:信號量是一個非負整數(車位數),全部經過它的線程/進程(車輛)都會將該整數減一(經過它固然是爲了使用資源),當該整數值爲零時,全部試圖經過它的線程都將處於等待狀態。在信號量上咱們定義兩種操做: Wait(等待) 和 Release(釋放)。當一個線程調用Wait操做時,它要麼獲得資源而後將信號量減一,要麼一直等下去(指放入阻塞隊列),直到信號量大於等於一時。Release(釋放)其實是在信號量上執行加操做,對應於車輛離開停車場,該操做之因此叫作「釋放」是由於釋放了由信號量守護的資源。
第一個CreateSemaphore
函數功能:建立信號量
函數原型:
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR lpName
);
函數說明:
第一個參數表示安全控制,通常直接傳入NULL。
第二個參數表示初始資源數量。
第三個參數表示最大併發數量。
第四個參數表示信號量的名稱,傳入NULL表示匿名信號量。
第二個 OpenSemaphore
函數功能:打開信號量
函數原型:
HANDLE OpenSemaphore(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
);
函數說明:
第一個參數表示訪問權限,對通常傳入SEMAPHORE_ALL_ACCESS。詳細解釋能夠查看MSDN文檔。
第二個參數表示信號量句柄繼承性,通常傳入TRUE便可。
第三個參數表示名稱,不一樣進程中的各線程能夠經過名稱來確保它們訪問同一個信號量。
第三個 ReleaseSemaphore
函數功能:遞增信號量的當前資源計數
函數原型:
BOOL ReleaseSemaphore(
HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount
);
函數說明:
第一個參數是信號量的句柄。
第二個參數表示增長個數,必須大於0且不超過最大資源數量。
第三個參數能夠用來傳出先前的資源計數,設爲NULL表示不須要傳出。
注意:當前資源數量大於0,表示信號量處於觸發,等於0表示資源已經耗盡故信號量處於末觸發。在對信號量調用等待函數時,等待函數會檢查信號量的當前資源計數,若是大於0(即信號量處於觸發狀態),減1後返回讓調用線程繼續執行。一個線程能夠屢次調用等待函數來減少信號量。
最後一個 信號量的清理與銷燬
因爲信號量是內核對象,所以使用CloseHandle()就能夠完成清理與銷燬了。
事件Event介紹和使用
第一個CreateEvent
函數功能:建立事件
函數原型:
HANDLECreateEvent(
LPSECURITY_ATTRIBUTESlpEventAttributes,
BOOLbManualReset,
BOOLbInitialState,
LPCTSTRlpName
);
函數說明:
第一個參數表示安全控制,通常直接傳入NULL。
第二個參數肯定事件是手動置位仍是自動置位,傳入TRUE表示手動置位,傳入FALSE表示自動置位。若是爲自動置位,則對該事件調用WaitForSingleObject()後會自動調用ResetEvent()使事件變成未觸發狀態。打個小小比方,手動置位事件至關於教室門,教室門一旦打開(被觸發),因此有人均可以進入直到老師去關上教室門(事件變成未觸發)。自動置位事件就至關於醫院裏拍X光的房間門,門打開後只能進入一我的,這我的進去後會將門關上,其它人不能進入除非門從新被打開(事件從新被觸發)。
第三個參數表示事件的初始狀態,傳入TRUR表示已觸發。
第四個參數表示事件的名稱,傳入NULL表示匿名事件。
第二個OpenEvent
函數功能:根據名稱得到一個事件句柄。
函數原型:
HANDLEOpenEvent(
DWORDdwDesiredAccess,
BOOLbInheritHandle,
LPCTSTRlpName //名稱
);
函數說明:
第一個參數表示訪問權限,對事件通常傳入EVENT_ALL_ACCESS。詳細解釋能夠查看MSDN文檔。
第二個參數表示事件句柄繼承性,通常傳入TRUE便可。
第三個參數表示名稱,不一樣進程中的各線程能夠經過名稱來確保它們訪問同一個事件。
第三個SetEvent
函數功能:觸發事件
函數原型:BOOLSetEvent(HANDLEhEvent);
函數說明:每次觸發後,必有一個或多個處於等待狀態下的線程變成可調度狀態。
第四個ResetEvent
函數功能:將事件設爲末觸發
函數原型:BOOLResetEvent(HANDLEhEvent);
最後一個事件的清理與銷燬
因爲事件是內核對象,所以使用CloseHandle()就能夠完成清理與銷燬了。
WaitForSingleObject介紹:
使用該函數監聽事件和信號量的觸發,對於信號量的觸發可使信號量的值減1.該函數每次只能監聽一個對象。
WaitForMultipleObjects介紹:
使用該函數監聽事件和信號量的觸發,對於信號量的觸發可使信號量的值減1.該函數每次只能監聽多個對象。
DWORD WaitForMultipleObjects(