我们编写多线程应用程序的时候,经常需要进行线程同步协作,我们来实践一下用信号量同步线程。请见代码实现与注释分析,
- /* 头文件 */
- #include <windows.h>
- #include <stdio.h>
- /* 常量定义 */
- #define NUMTHREADS 4
- /* 全局变量 */
- HANDLE hSemaphore;
- /* 函数声明 */
- void UseSemaphore(void);
- DWORD WINAPI SemaphoreThread(LPVOID lpParam);
- /*************************************
- * int main(void)
- * 功能 演示
- *
- * 参数 未使用
- **************************************/
- int main()
- {
- UseSemaphore() ;
- }
- /*************************************
- * DWORD WaitForAllThread(HANDLE hThread[], DWORD dwNumThread)
- * 功能 等待指定的线程都结束
- *
- * 参数 HANDLE hThread[] 需要等待结束的线程句柄数组
- * DWORD dwNumThread 线程句柄数组的大小
- **************************************/
- DWORD WaitForAllThread(HANDLE hThread[], DWORD dwNumThread)
- {
- // 等待所有线程结束
- DWORD dwWaitResult = WaitForMultipleObjects(
- dwNumThread,
- hThread, // 线程句柄作为等待对象
- TRUE,
- INFINITE);
- switch (dwWaitResult)
- {
- case WAIT_OBJECT_0:
- printf("\nAll thread exit\n");
- break;
- default:
- printf("\nWait error: %u", GetLastError());
- }
- return 0;
- }
- /*************************************
- * void UseSemaphore(void)
- * 功能 演示UseSemaphore的使用方法
- *
- * 参数 未使用
- **************************************/
- void UseSemaphore(void)
- {
- HANDLE hThread[NUMTHREADS];
- INT i;
- LONG lMax;
- CHAR cMax;
- // 打印信息获取输入
- printf("将创建%d个进程,获得信号量的进程可以向屏幕打印。\n"
- "请输入信号量的最大计数1~%d:",NUMTHREADS,NUMTHREADS);
- // 获得输入的字符
- cMax = getch();
- printf("%c\n",cMax);
- // 将字符转换为数字
- lMax = cMax & 0xF;
- if(lMax<0 || lMax>NUMTHREADS)
- {
- printf("请输入1-%d",NUMTHREADS);
- }
- // 创建信号量
- hSemaphore = CreateSemaphore(
- NULL, // 默认安全属性
- lMax, // 初始化计数器,用户输入
- lMax, // 最大计数,用户输入
- NULL); // 未命名
- if (hSemaphore == NULL)
- {
- printf("CreateSemaphore error: %d\n", GetLastError());
- }
- // 创建多个线程 访问共享资源
- for(i = 0; i < NUMTHREADS; i++)
- {
- hThread[i] = CreateThread(NULL, 0,
- SemaphoreThread,
- &i, // 进程序号作为参数
- 0, NULL);
- if (hThread[i] == NULL)
- {
- printf("CreateThread failed (%d)\n", GetLastError());
- return;
- }
- }
- // 等待所有线程都执行完成并退出
- WaitForAllThread(hThread,NUMTHREADS);
- }
- /*************************************
- * DWORD WINAPI SemaphoreThread(LPVOID lpParam)
- * 功能 线程函数,读共享内存
- *
- * 参数 未使用
- **************************************/
- DWORD WINAPI SemaphoreThread(LPVOID lpParam)
- {
- DWORD dwWaitResult;
- BYTE lpRead[16];
- //DWORD i = *(LPWORD)lpParam; // 线程的编号
- DWORD dwPreviousCount;
- DWORD j = 0;
- // 每个线程都将访问3次受限资源
- for(; j<3; j++)
- {
- // 线程可以在此进行一些操作
- // 以暂停随机长的时间模拟真实情况
- Sleep(rand()%1000);
- // 等待信号量
- dwWaitResult = WaitForSingleObject(
- hSemaphore, // 信号量句柄
- INFINITE); // 无限等待
- switch (dwWaitResult)
- {
- case WAIT_OBJECT_0:
- printf("\nProcess %d Gets Semaphore",GetCurrentThreadId());
- break;
- default:
- printf("\nprocess %u Wait error: %u",GetCurrentThreadId(), GetLastError());
- }
- // 获得信息量后访问受限资源
- // 以等待随机长时间模块真实情况
- Sleep(rand()%1000);
- // 释放信号量
- if (!ReleaseSemaphore(
- hSemaphore, // 信号量句柄
- 1, // 释放后计数器减1
- &dwPreviousCount) ) // 获得计数
- {
- printf("\nprocess %u ReleaseSemaphore error: %d", GetCurrentThreadId(), GetLastError());
- }
- else
- {
- printf("\nProcess %u release Semaphore, previous count is %u",
- GetCurrentThreadId(), dwPreviousCount);
- }
- }
- return 1;
- }