在Windows编程中,线程同步是一个非常重要的概念。为了实现多线程之间的协调工作,Windows提供了多种同步对象,如事件(Event)、互斥量(Mutex)、信号量(Semaphore)等。其中,事件是一种轻量级的同步机制,而`SetEvent`和`WaitForSingleObject`是操作事件的两个核心函数。
什么是事件?
事件(Event)是Windows系统提供的一种内核对象,用于通知一个或多个等待线程某个条件已经满足。事件可以分为两种类型:手动重置事件和自动重置事件。
- 手动重置事件:当事件被设置后,所有等待该事件的线程都会被唤醒。即使只有一个线程执行完后,其他线程仍然处于就绪状态。
- 自动重置事件:当事件被设置后,只有一个等待的线程会被唤醒,然后事件会自动复位,其他等待的线程将继续保持等待状态。
SetEvent函数
`SetEvent`函数用于将指定的事件对象设置为有信号状态。一旦事件变为有信号状态,等待该事件的线程就可以继续执行。
函数原型:
```c
BOOL SetEvent(HANDLE hEvent);
```
- `hEvent`:指向要设置的事件对象句柄。
- 返回值:如果函数成功,则返回非零值;否则返回零。
WaitForSingleObject函数
`WaitForSingleObject`函数用于等待一个对象变为有信号状态。它会阻塞调用线程,直到指定的对象变为有信号状态或者超时。
函数原型:
```c
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
```
- `hHandle`:要等待的对象句柄,可以是事件、互斥量、信号量等。
- `dwMilliseconds`:指定等待的时间,单位为毫秒。如果设置为`INFINITE`,表示无限期等待。
- 返回值:如果对象变为有信号状态,则返回`WAIT_OBJECT_0`;如果超时,则返回`WAIT_TIMEOUT`。
示例代码
下面通过一个简单的例子来展示如何使用`SetEvent`和`WaitForSingleObject`来实现线程间的同步:
```c
include
include
HANDLE hEvent;
void ThreadFunction(LPVOID lpParam) {
printf("子线程开始等待事件...\n");
WaitForSingleObject(hEvent, INFINITE); // 等待事件被设置
printf("子线程收到通知,继续执行任务。\n");
}
int main() {
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // 创建一个手动重置事件
if (hEvent == NULL) {
printf("创建事件失败!\n");
return 1;
}
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunction, NULL, 0, NULL);
if (hThread == NULL) {
printf("创建线程失败!\n");
CloseHandle(hEvent);
return 1;
}
Sleep(3000); // 主线程延迟3秒
printf("主线程设置事件...\n");
SetEvent(hEvent); // 设置事件,通知子线程
WaitForSingleObject(hThread, INFINITE); // 等待子线程完成
CloseHandle(hThread);
CloseHandle(hEvent);
printf("程序结束。\n");
return 0;
}
```
运行结果
运行上述代码后,你会看到类似以下输出:
```
子线程开始等待事件...
主线程设置事件...
子线程收到通知,继续执行任务。
程序结束。
```
总结
通过`SetEvent`和`WaitForSingleObject`的配合使用,我们可以轻松实现线程间的同步。理解事件的不同类型及其行为对于编写高效且可靠的多线程程序至关重要。希望本文能帮助你更好地掌握这两个函数的用法。