基于visual c++之windows核心编程代码分析(12)使用信号量同步线程
2016-12-08 21:54
711 查看
我们编写多线程应用程序的时候,经常需要进行线程同步协作,我们来实践一下用信号量同步线程。请见代码实现与注释分析,
[cpp] view
plain copy
/* 头文件 */
#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;
}
[cpp] view
plain copy
/* 头文件 */
#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;
}
相关文章推荐
- 基于visual c++之windows核心编程代码分析(15)使用Mutex同步线程
- 基于visual c++之windows核心编程代码分析(14)使用Event同步线程
- 基于visual c++之windows核心编程代码分析(55)使用GoogleUrl方便安全地解析URL
- 基于visual c++之windows核心编程代码分析(56)使用winsock搜索蓝牙设备
- 基于visual c++之windows核心编程代码分析(20) 纤程与线程的互相转换
- 基于visual c++之windows核心编程代码分析(56)使用winsock搜索蓝牙设备
- 基于visual c++之windows核心编程代码分析(55)使用GoogleUrl方便安全地解析URL
- 基于visual c++之windows核心编程代码分析(16)使用邮槽进行进程通信
- 基于visual c++之windows核心编程代码分析(52)使用WMI 获取进程启动参数
- 基于visual c++之windows核心编程代码分析(56)使用winsock搜索蓝牙设备
- 基于visual c++之windows核心编程代码分析(52)使用WMI 获取进程启动参数
- 基于visual c++之windows核心编程代码分析(20) 纤程与线程的互相转换
- 基于visual c++之windows核心编程代码分析(56)使用winsock搜索蓝牙设备
- 基于visual c++之windows核心编程代码分析(29)ICMP实现远程控制
- 基于visual c++之windows核心编程代码分析(38)实践服务器压力测试-SYN请求
- 基于visual c++之windows核心编程代码分析(38)实践服务器压力测试-SYN请求
- 基于visual c++之windows核心编程代码分析(37)实践信息安全隐患监测-嗅探
- 基于visual c++之windows核心编程代码分析(36)实践SYN安全隐患监测
- 基于visual c++之windows核心编程代码分析(31)SNMP协议编程
- 基于visual c++之windows核心编程代码分析(37)实践信息安全隐患监测-嗅探