1、預備知識
臨界區非常适合同一程序中對資料的串行通路,它的速度很快。然而,也許你想要使某些應用程式與機器中的其它事件或者其它程序取得同步,這時你就要使用一些核心對象來同步線程。核心對象包括:
.程序
.線程
.檔案
.檔案變化通知(File Change notification)
.控制台輸入(Console input)
.互斥量(Mutex)
.信号量(Semaphore)
.事件(Event)
每個對象在任何時候都可以處于兩種狀态之一:有信号(Signaled)和無信号(not signaled)。線程能被置于睡眠狀态直到一個對象變成有信号的。
線程主要使用下面兩個函數來使自己睡眠,以便等待核心對象變成有信号的:
DWORD WaitForSingleObject(
HANDLE hHandle, // 等待的核心變量的句柄
DWORD dwMilliseconds // 等候的時間,如果是0,隻測試下狀态,如果是INFINITE,則一直等待直到有信号
);
和
DWORD WaitForMultipleObjects(
DWORD nCount, //檢查核心對象的數目,最大值為64
CONST HANDLE *lpHandles, // 核心對象句柄數組的指針
BOOL bWaitAll, // 等待的标志
DWORD dwMilliseconds // 同WaitForSingleObject
WaitForSingleObject的傳回值為:
傳回值: 定義: 含義:
WAIT_OBJECT_0 0x00000000 對象到達信号狀态
WAIT_TIMEOUT 0x00000102 對象沒有在dwMilliseconds内達到有信号狀态
WAIT_ABANDONED 0x00000080 對象是一個互斥量,由于它被放棄了而達到了有信号狀态
WAIT_FAILED 0xFFFFFFFF 發生了錯誤,可以調用GetLastError得到擴充錯誤資訊
WaitForMultipleObjects和WaitForSingleObject類似,不過它等待若幹個對象變成有信号的或等一個清單對象的對象中的某一個變成有信号的。bWaitAll指定是等待清單中的一個達到狀态還是等待所有的,若為True則等待所有的,為FALSE等待直到對象中至少一個變成有信号的。
WaitForMultipleObjects的傳回值為:
WAIT_OBJECT_0(WAIT_OBJECT_0+cObjects-1) 0x00000000 當是等待所有對象變成有狀态時,這一值表明等待成功完成。當是等待任一對象時,傳回值是變得有信号對象的在lpHandles所指句柄數組的下标
WAIT_TIMEOUT 0x00000102 對象或對象們沒有在dwMilliseconds内達到有信号狀态
WAIT_ABANDONED_0(WAIT_ABANDONED_0+cObjects-1) 0x00000080 對象是一個互斥量,由于它被放棄了而達到了有信号狀态。傳回值情況似類上面的WAIT_OBJECT_0,分兩種情況。
2、互斥量
互斥量和臨界區很相似,隻不過它們可以被用來同步多個程序間的資料通路。為此,兩個程序間的某個線程必須擁有同一互斥量對象的程序相關句柄。
3、使用互斥量
要使用互斥量,必須先調用CreateMutex 建立此互斥量:
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName
其中:
lpMutexAttributes參數指向一個SECURITY_ATTRIBUTES結構,這個結構在98中将被忽略,在NT/2K中它指定一個安全描述,如果忽略這個,Mutex将得到一個預設的安全描述。bInitialOwner參數如果為True表示此線程将擁有此互斥量,是以互斥量将處于無信号狀态。任何在此互斥量上等待的線程都将被挂起,直到建立此互斥量的線程釋放它。如果此參數為FALSE,就表示此互斥量不被任何線程擁有,因而建立後處于有信号狀态。第一個等待此互斥量的線程将立刻獲得此互斥量的所有權并繼續運作。lpName參數要麼是NULL,要麼是一個标志互斥量的以0為結束符的字元串做為名字。
在調用CreateMutex後要立即調用GetLasrError,如果傳回值為ERROR_ALREADY_EXISTS,就表明沒有建立新的互斥量對象。
當要釋放一個互斥量的所有權時調用BOOL ReleaseMutex(HANDLE hMutex)。和臨界區一樣,互斥量有着與之相聯系的所有權計數,如果某線程擁有了互斥量再次調用WaitForSingleObject時,該互斥量的引用計數将增加,是以必須調用相同次數的ReleaseMutex來釋放此互斥量。當互斥量使用完後調用CloseHandle關閉互斥量。
4、互斥量同步程序
要使用互斥量來同步程序,兩個程序中的某個程序必須擁有同一互斥量對象的程序相關句柄。可以通過兩種方法獲得此句柄。一是在第二個線程建立互斥量時使用與第一個互斥量一樣的lpName,此時就不再建立新的互斥量而是傳回辨別已有互斥量的程序相關句柄。另一種獲得的方法是使用
HANDLE OpenMutex(
DWORD dwDesiredAccess, // MUTEX_ALL_ACCESS或SYNCHRONIZE(NT Only)
BOOL bInheritHandle, // 指明此程序建立的任一子程序是否應該繼承此互斥量。
LPCTSTR lpName // 互斥量的名字
調用OpenMutex時,系統将掃描所有現存的互斥量,如果找到lpName指定的互斥量。就傳回給調用線程,如果找不到就傳回NULL。