進程中線程同步的四種常用方式: 1、 臨界區(CCriticalSection) 當多個線程訪問一個獨占性共享資源時,可以使用臨界區對象。擁有臨界區的線程可以訪問被保護起來的資源或代碼段,其他線程若想訪問,則被掛起,直到擁有臨界區的線程放棄臨界區為止。具體應用方式: 1、 定義臨界區對象CcriticalSection g_CriticalSection; 2、 在訪問共享資源(代碼或變量)之前,先獲得臨界區對象,g_CriticalSection.Lock(); 3、 訪問共享資源后,則放棄臨界區對象,g_CriticalSection.Unlock(); 2、 事件(CEvent) 事件機制,則允許一個線程在處理完一個任務后,主動喚醒另外一個線程執行任務。比如在某些網絡應用程序中,一個線程如A負責偵聽通信端口,另外一個線程B負責更新用戶數據,利用事件機制,則線程A可以通知線程B何時更新用戶數據。每個Cevent對象可以有兩種狀態:有信號狀態和無信號狀態。Cevent類對象有兩種類型:人工事件和自動事件。 自動事件對象,在被至少一個線程釋放后自動返回到無信號狀態; 人工事件對象,獲得信號后,釋放可利用線程,但直到調用成員函數ReSet()才將其設置為無信號狀態。在創建Cevent對象時,默認創建的是自動事件。 CEvent(BOOL bInitiallyOwn=FALSE, BOOL bManualReset=FALSE, LPCTSTR lpszName=NULL, LPSECURITY_ATTRIBUTES lpsaAttribute=NULL); bInitiallyOwn:指定事件對象初始化狀態,TRUE為有信號,FALSE為無信號; bManualReset:指定要創建的事件是屬於人工事件還是自動事件。TRUE為人工事件,FALSE為自動事件; 后兩個參數一般設為NULL,在此不作過多說明。 2、BOOL CEvent::SetEvent(); 將Cevent類對象的狀態設置為有信號狀態。如果事件是人工事件,則Cevent類對象保持為有信號狀態,直到調用成員函數ResetEvent()將其重新設為無信號狀態時為止。如果為自動事件,則在SetEvent()后將事件設置為有信號狀態,由系統自動重置為無信號狀態。 3、BOOL CEvent::ResetEvent(); 將事件的狀態設置為無信號狀態,並保持該狀態直至SetEvent()被調用為止。由於自動事件是由系統自動重置,故自動事件不需要調用該函數。 一般通過調用WaitForSingleObject()函數來監視事件狀態。 3、 互斥量(CMutex) 互斥對象和臨界區對象非常相似,只是其允許在進程間使用,而臨界區只限制與同一進程的各個線程之間使用, 但是更節省資源,更有效率。 4、 信號量(CSemphore) 當需要一個計數器來限制可以使用某共享資源的線程數目時,可以使用“信號量”對象。CSemaphore類對象保存了對當前訪問某一個指定資源的線程的計數值,該計數值是當前還可以使用該資源的線程數目。如果這個計數達到了零,則所有對這個CSemaphore類對象所控制的資源的訪問嘗試都被放入到一個隊列中等待,直到超時或計數值不為零為止。 CSemaphore 類的構造函數原型及參數說明如下: CSemaphore( LONG lInitialCount = 1, LONG lMaxCount = 1, LPCTSTR pstrName = NULL, LPSECURITY_ATTRIBUTES lpsaAttributes = NULL ); lInitialCount:信號量對象的初始計數值,即可訪問線程數目的初始值; lMaxCount:信號量對象計數值的最大值,該參數決定了同一時刻可訪問由信號量保護的資源的線程最大數目; 后兩個參數在同一進程中使用一般為NULL,不作過多討論; 一般是將當前可用資源計數設置為最大資源計數,每增加一個線程對共享資源的訪問,當前可用資源計數就減1,只要當前可用資源計數大於0,就可以發出信號量信號。如果為0,則放入一個隊列中等待。線程在處理完共享資源后,應在離開的同時通過ReleaseSemaphore()函數將當前可用資源數加1。 BOOL ReleaseSemaphore( HANDLE hSemaphore, // hSemaphore:信號量句柄 LONG lReleaseCount, // lReleaseCount:信號量計數值 LPLONG lpPreviousCount // 參數一般為NULL);