分类: C/C++
2008-04-03 13:52:39
函数 | 参数和功能 |
InterlockedIncrement | 参数为PLONG类型。此函数使一个LONG变量增1 |
InterlockedDecrement | 参数为PLONG类型。此函数使一个LONG变量减1 |
InterlockedExchangeAdd | 参数1为PLONG类型,参数2为LONG类型。此函数将参数2赋给参数1指向的值 |
InterlockedExchange | 参数1为PLONG类型,参数2为LONG类型。此函数将参数2的值赋给参数1指向的值 |
InterlockedExchangePointer | 参数为PVOID* 类型,参数2为PVOID类型。此函数功能同上。具体参见帮助 |
InterlockedCompareExchange | 参数1为PLONG类型,参数2为LONG类型,参数3为LONG类型。此函数将参数1指向的值与参数3比较,相同则把参数2的值赋给参数1指向的值。不相同则不变 |
InterlockedCompareExchangePointer | 参数1为PVOID* 类型,参数2为PVOID类型,参数3为PVOID。此函数功能同上。具体参见帮助 |
2、临界区
临界区对象运行在用户模式。它能保证在临界区内所有被访问的资源不被其它线程访问,直到当前线程执行完临界区代码。除了API外,MFC也对临界区函数进行了封装。临界区相关函数:
void InitializeCriticalSection ( LPCRITICAL_SECTION ); void EnterCriticalSection ( LPCRITICAL_SECTION ); void LeaveCriticalSection ( LPCRITICAL_SECTION ); void DeleteCriticalSection ( LPCRITICAL_SECTION );举例如下:
void CriticalSectionExample (void) { CRITICAL_SECTION csMyCriticalSection; InitializeCriticalSection (&csMyCriticalSection); ///初始化临界区变量 __try { EnterCriticalSection (&csMyCriticalSection); ///开始保护机制 ///此处编写代码 } __finally ///异常处理,无论是否异常都执行此段代码 { LeaveCriticalSection (&csMyCriticalSection); ///撤销保护机制 } }MFC类使用更简单:
CCriticalSection cs; cs.Lock(); ///编写代码 cs.Unlock();使用临界区要注意的是避免死锁。当有两个线程,每个线程都有临界区,而且临界区保护的资源有相同的时候,这时就要在编写代码时多加考虑。
函数 | 参数和功能 |
WaitForSingleObject | 参数1为HANDLE类型,参数2为DWORD类型。此函数等待参数1标识的事件,等待时间为参数2的值,单位ms。如果不超时,当事件成为有信号状态时,线程唤醒继续运行。 |
WaitForMultipleObjects | 参数1为DWORD类型,参数2为HANDLE * 类型,参数3为BOOL类型,参数4为DWORD类型。此函数等待参数2指向的数组中包含的所有事件。如果不超时,当参数3为FALSE时,只要有一个事件处于有信号状态,函数就返回这个事件的索引。参数3为TRUE时,等待所有事件都处于有信号状态时才返回。 |
MsgWaitForMultipleObjects | 参数1为DWORD类型,参数2为LPHANDLE类型,参数3为BOOL类型,参数4为DWORD类型,参数5为DWORD类型。此函数功能上同WaitForMultipleObjects函数相似,只是多了一个唤醒掩码。唤醒掩码都是和消息有关的。此函数不但能够为事件等待,还能为特定的消息等待。其实这个函数就是专为等待消息而定义的。 |
MsgWaitForMultipleObjectsEx | 参数1为DWORD类型,参数2为LPHANDLE类型,参数3为DWORD类型,参数4为DWORD类型,参数5为DWORD类型。此函数是MsgWaitForMultipleObjects函数的扩展。将原来函数的参数3除掉,添加参数5为标志。标志有两个值:0或MWMO_INPUTAVAILABLE。 |
如果一个线程既要执行大量任务同时又要响应用户的按键消息,这两个专用于等待消息的函数将非常有用。
和事件有关的函数有:
HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPTSTR lpName); BOOL SetEvent(HANDLE hEvent ); BOOL PulseEvent(HANDLE hEvent); BOOL ResetEvent(HANDLE hEvent); HANDLE OpenEvent(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName );事件对象是最常用的内核模式同步方法。它包含一个使用计数和两个BOOL变量。其中一个BOOL变量指定这个事件对象是自动重置还是手工重置。另一个BOOL变量指定当前事件对象处于有信号状态还是无信号状态。
HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName); BOOL ReleaseMutex(HANDLE hMutex);互斥对象包含一个引用计数,一个线程ID和一个递归计数。引用计数是所有内核对象都含有的。线程ID表示哪个线程正在使用互斥资源,当ID为0时,互斥对象发出信号。递归计数用于一个线程多次等待同一个互斥对象。函数CreateMutex创建一个互斥对象,参数1必须设置为NULL,参数2如果设置为FALSE,表示当前线程并不占有互斥资源,互斥对象的线程ID和递归计数都被设置为0,互斥对象处于有信号状态。如果设置为TRUE,表示当前线程将占有互斥资源,互斥对象的线程ID被设置为当前线程ID,递归计数被设置为1,互斥对象处于无信号状态。当调用等待函数时,等待函数检验互斥对象的线程ID是否为0,如果为0,说明当前没有线程访问互斥资源,内核将线程唤醒,并且将互斥对象的递归计数加1。当一个线程被唤醒后,必须调用函数ReleaseMutex将互斥对象的递归计数减1。如果一个线程多次调用等待函数,就必须以同样的次数调用ReleaseMutex函数。与其它Windows不同的是,和互斥相关的函数中没有OpenMutex函数。要在不同进程中访问同一互斥对象,调用CreateMutex函数,参数传递互斥对象的名称,返回这个互斥对象的句柄。
HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName); BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount);函数CreateSemaphore的参数1为NULL,参数2为当前可用资源初始值,参数3为最大可用资源数,参数4为名字。当参数2的值等于0时,信标对象处于无信号状态,这时内核将调用等待函数的线程置于睡眠状态,如果参数2的值大于0,信标对象处于有信号状态,这时内核将调用等待函数的线程置于运行状态,并将信标对象的当前可用资源数减1。函数ReleaseSemaphore的参数1为信标对象的句柄,参数2为要释放的资源数,参数3返回原来可用资源数,调用此函数将当前可用资源数加上参数2的值。当一个线程访问完可用资源后,应该调用ReleaseSemaphore函数使当前可用资源数递增。要在不同进程中访问同一信标对象,调用CreateSemaphore函数并传递信标对象的名称,得到已经在其它进程创建的信标对象的句柄。CE下没有OpenSemaphore函数。另外我还要说明一点,等待函数默认将信标对象的当前可用资源数减1,但线程可能一次使用多个资源,这就可能出现问题了。为避免问题出现,应该遵守一个线程只使用一个资源的原则。
HANDLE WINAPI CreateMsgQueue(LPCWSTR lpszName, LPMSGQUEUEOPTIONS lpOptions); BOOL WINAPI CloseMsgQueue(HANDLE hMsgQ); BOOL GetMsgQueueInfo(HANDLE hMsgQ, LPMSGQUEUEINFO lpInfo); HANDLE WINAPI OpenMsgQueue(HANDLE hSrcProc, HANDLE hMsgQ, LPMSGQUEUEOPTIONS lpOptions); BOOL ReadMsgQueue(HANDLE hMsgQ, LPVOID lpBuffer, DWORD cbBufferSize, LPDWORD lpNumberOfBytesRead, DWORD dwTimeout, DWORD *pdwFlags); BOOL WINAPI WriteMsgQueue(HANDLE hMsgQ, LPVOID lpBuffer, DWORD cbDataSize, DWORD dwTimeout, DWORD dwFlags);使用CreateMsgQueue函数创建一个消息队列,传递一个MSGQUEUEOPTIONS结构指针。在这个结构中设置标志(允许队列缓冲区动态改变大小,允许直接读或者写操作而不管之前是否有过写操作或读操作)、队列允许的最大消息数、队列属性(只读或者只写)。使用WriteMsgQueue函数把一个消息写入到消息队列中。传递一个消息队列的缓冲区、消息数据的大小、写入缓冲区的超时值、标志。使用ReadMsgQueue函数把一个消息从消息队列中读出。使用CloseMsgQueue函数关闭消息队列缓冲区。使用OpenMsgQueue函数能够打开其它进程中创建的消息队列。另外可以用等待函数等待消息队列的变化。当消息队列由没有消息到有消息时,或由满消息到不满消息时唤醒调用等待函数的线程。关于消息队列我并没有实验过,MSDN上有几个简单的例子。