虽然用户方式的线程同步机制具有速度快的优点,但是它也有其局限性。对于许多应用程序来说,这种机制是不适用的。例如,互锁函数家族只能在单值上运行,根本无法使线程进入等待状态。可以使用关键代码段使线程进入等待状态,但是只能用这些代码段对单个进程中的线程实施同步。还有,使用关键代码段时,很容易陷入死锁状态,因为在等待进入关键代码段时无法设定超时值。
内核对象机制的适应性远远优于用户方式机制,唯一不足之处是速度慢。
当进程正在运行的时候,进程内核对象处于未通知状态,当进程终止运行的时候,它就变为已通知状态。进程内核对象中是个布尔值,当对象创建时,该值被初始化为FA L S E(未通知状态)。当进程终止运行时,操作系统自动将对应的对象布尔值改为T R U E,表示该对象已经得到通知。
下面的内核对象可以处于已通知状态和未通知状态:
进程 线程 作业 文件修改通知 事件 可等待定时器 文件 信标 控制台输入 互斥对象
每个内核对象只是内核分配的一个内存块,并且只能由该内核访问。该内存块是一种数据结构,它的成员负责维护该对象的各种信息。
一、等待函数
等待函数可使线程自愿进入等待状态,直到一个特定的内核对象变为已通知状态为止。
DWORD WaitForSingleObject(HANDLE hObject, DWORD dwMilliseconds);
DWORD WaitForMultipleObjects(DWORD dwCount, CONST HANDLE *phObjects, BOOL fWaitAll,DWORD dwMilliseconds);
dwCount:内核对象的数量
phObjects:指向内核对象句柄的数组的指针
fWaitAll:TRUE 直到所有指定的内核对象都变为已通知状态,返回值是WAIT_OBJECT_0; FALSE 直到指定的内核对象中的任何一个变为已通知状态,返回值是WAIT_OBJECT_0与(WAIT_OBJECT_0+dwCount-1)之间的一个值。
dwMilliseconds:超时值,INFINITE为不限时。
二、事件内核对象
事件内核对象包含一个使用计数;一个用于指明该事件是个自动重置韩式人工重置的事件的布尔值;另一个用于指明该事件处于已通知状态还是未通知状态的布尔值。
人工重置的事件,得到通知时,等待该事件的所有线程均变为可调度线程。自动重置的事件,得到通知时,等待该事件的线程中只有一个线程变为可调度线程。
创建事件内核对象:HANDLE CreateEvent(PSECURITY_ATTRIBUTES psa,BOOL fManualReset, BOOL fInitialState, PCTSTR pszName);
fMannualReset:TRUE 人工重置的事件; FALSE 自动重置的事件。
fInitialState:TRUE 已通知状态;FALSE 未通知状态。
当系统创建事件对象后,createEvent就将与进程相关的句柄返回给事件对象。通过pszName参数中传递相同的值,其他进程中的线程可以获得对该对象的访问权。
HANDLE OpenEvent(DWORD fdwAccess, BOOL fInherit, PCTSTR pszName);
当不再需要事件内核对象时,应该调用CloseHandle函数。
BOOL SetEvent(HANDLE hEvent);改为已通知状态。
BOOL ResetEvent(HANDLE hEvent);改为未通知状态。
三、等待定时器内核对象
等待定时器是在某个时间或按规定的间隔时间发出自己的信号通知的内核对象。通常用来在某个时间执行某个操作。
HANDLE CreateWaitableTimer(PSECURITY_ATTRIBUTES psa, BOOL fManualReset, PCTSTR pszName);
HANDLE OpenWaitableTimer(dwDesiredAccess, BOOL bInheritHandle, PCTSTR pszName);
BOOL SetWaitableTimer(HANDLE hTimer,const LARGE_INTEGER *pDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletionRoutine,
PVIOD pvArgToCompletionRoutine, BOOL fResume);
hTimer:指明你要设置的定时器
pDueTime:指明定时器何时应该第一次报时
lPeriod:指明此后定时器应该间隔多长时间报时一次
四、信标内核对象
信标内核对象用于对资源进行计数。
HANDLE CreateSemaphore(PSECURITY_ATTRIBUTE psa,LONG lInitialCount,LONG lMaximumCount,PCTSTR pszName);
HANDLE OpenSemaphore(DWORD fdwAccess,BOOL bInheritHandle, PCTSTR pszName);
BOOL ReleaseSemaphore(HANDLE hsem, LONG lReleaseCount, PLONG plPreviousCount);
五、互斥内核对象
互斥对象内核对象确保线程对单个资源的互斥访问权。包含一个使用数量,一个线程ID和一个递归计数器。互斥对象的行为特性与关键代码段相同,但是互斥对象属于内核对象,而关键代码段则属于用户方式对象。
ID用于标识系统中的哪个线程当前拥有互斥对象,递归计数器用于指明该线程拥有互斥对象的次数。
HANDLE CreateMutex(PSECURITY_ATTRIBUTE psa,BOOL bInitialOwner,PCTSTR pszName);
HANDLE OpenMutex(DWORD fdwAccess, BOOL bInheritHandle, PCTSTR pszName);
BOOL ReleaseMutex(HANDLE hMutex);