/* 本实例示范使用事件对象实现线程间同步[事件对象属于内核对象, */ /* 它可以实现在不同的进程的不同线程间的同步, */ /* 可以将本exe程序复制不同名字的文件然后运行, */ /* 会发现即使重命名文件仍然不能同时运行多个exe] */ #include <stdio.h> #include <windows.h> DWORD WINAPI Fun1Proc( LPVOID lpParameter // thread data ); DWORD WINAPI Fun2Proc( LPVOID lpParameter // thread data ); HANDLE hEvent = NULL; int tickets = 100; /* 对于人工重置的事件对象,当事件对象变为有信号状态时,所有等待线程都可以运行,获得该事件对象的线程并不会将该事件对象设置无信号状态;*/ /* 对于自动重置事件对象,当事件对象变为有信号状态时,只有一个等待线程可以运行,获得该事件对象的线程同时将该事件对象设为无信号状态 */ void main() { HANDLE hThread1 = CreateThread(NULL,0,Fun1Proc,NULL,0,NULL); HANDLE hThread2 = CreateThread(NULL,0,Fun2Proc,NULL,0,NULL); CloseHandle(hThread1); CloseHandle(hThread2); hEvent = CreateEvent(NULL,FALSE,FALSE,"tickets");//创建一个无信号状态的自动重置事件对象 if (hEvent && GetLastError()==ERROR_ALREADY_EXISTS)//判断该命名事件对象是否已经创建过[确保应用程序只能有一个实例运行] { printf("only one instance can running/n"); return; } Sleep(10000);//睡眠会使事件对象被设置为有信号状态 CloseHandle(hEvent); } DWORD WINAPI Fun1Proc( LPVOID lpParameter // thread data ) { while (TRUE) { WaitForSingleObject(hEvent,INFINITE);//由于是一个自动重置事件,因此操作系统会自动将此事件对象设置为无信号状态 //ResetEvent(hEvent); if (tickets==0) { break; } Sleep(1); printf("Thread1 sell ticket:%d/n",tickets--); SetEvent(hEvent);//重置事件对象为有信号状态 } return 0; } DWORD WINAPI Fun2Proc( LPVOID lpParameter // thread data ) { while (TRUE) { WaitForSingleObject(hEvent,INFINITE);//由于是一个自动重置事件,因此操作系统会自动将此事件对象设置为无信号状态 //ResetEvent(hEvent); if (tickets==0) { break; } Sleep(1); printf("Thread2 sell ticket:%d/n",tickets--); SetEvent(hEvent);//重置事件对象为有信号状态 } return 0; }