Windows 使用C++编程进程、线程、临界区等问题范例

本文主要说明了线程间互斥的方法:

1. 互斥量

2. 临界区

3. 事件

进程间互斥的方法:使用进程的互斥对象,防止进程多次实例化;

 

1. 线程启动

#include <windows.h>								//包含相应头文件
#include <stdio.h>	
							
DWORD WINAPI myfun1(LPVOID lpParameter 	);			//声明线程函数
DWORD WINAPI myfun2(LPVOID lpParameter 	);

int main()											//主函数
{
	HANDLE h1,h2;										//定义句柄变量
	h1=::CreateThread(NULL,0,myfun1,NULL,0,NULL);		//创建线程1
	printf("线程1开始运行!\r\n");						//输出线程1运行信息
	h2=::CreateThread(NULL,0,myfun2,NULL,0,NULL);		//创建线程2
	printf("线程2开始运行!\r\n");						//输出线程2运行信息
	::CloseHandle(h1);									//关闭线程句柄对象
	::CloseHandle(h2);
	while(1)
	{
		if(getchar()=='q')								//如果用户输入字符q
		{
			return 0;										//程序正常退出
		}
		else												//如果用户输入的字符不是q
		{
			::Sleep(100);									//程序睡眠
		}
	}
}

DWORD WINAPI myfun1(LPVOID lpParameter) 			//分别实现线程函数
{
	printf("线程1正在运行!\r\n");						//输出信息
	return 0;											//正常结束线程函数
}
DWORD WINAPI myfun2(LPVOID lpParameter) 
{
	printf("线程2正在运行!\r\n");
	return 0;
}

2. MFC互斥对象

#include <afxmt.h>
#include <stdio.h>

DWORD WINAPI myfun1(LPVOID lpParameter);//声明线程函数
DWORD WINAPI myfun2(LPVOID lpParameter);
CMutex hmutex(NULL,FALSE,NULL);				//定义全局互斥对象
int a=0;										//定义全局变量a

int main()
{	
	HANDLE h1,h2;									//定义线程句柄
	h1=::CreateThread(NULL,0,myfun1,NULL,0,NULL);	//创建线程1
	printf("使用CMutex 类实现线程同步\r\n");
	printf("线程1开始运行!\r\n");
	h2=::CreateThread(NULL,0,myfun2,NULL,0,NULL);	//创建线程2
	printf("线程2开始运行!\r\n");
	::CloseHandle(h1);								//关闭线程句柄对象
	::CloseHandle(h2);
	::Sleep(10000);									//程序睡眠10秒
	return 0;
}

DWORD WINAPI myfun1(LPVOID lpParameter) 		//线程函数1
{
	while(1)
	{
		hmutex.Lock(INFINITE);						//锁定互斥对象
		if(a<10000)
		{
			a+=1;											//变量自加
			::Sleep(1000);									//线程睡眠1秒
			printf("线程1:%d\r\n",a);
			hmutex.Unlock();							//释放互斥对象
		}
		else
		{
			hmutex.Unlock();								//释放互斥对象
			break;										//跳出循环
		}
	}
    return 0;	
}
DWORD WINAPI myfun2(LPVOID lpParameter) 		//线程函数2
{
	while(1)
	{
		hmutex.Lock(INFINITE);						//锁定互斥对象
		if(a<10000)
		{
			a+=1;
			::Sleep(1000);
			printf("线程2:%d\r\n",a);					//输出变量
			hmutex.Unlock();							//释放互斥对象
		}
		else
		{	
			hmutex.Unlock();							//释放互斥对象
			break;										//跳出循环
		}
	}
    return 0;									//线程正常退出
}

3. MFC临界区

#include <stdio.h>
#include <afxmt.h>

DWORD WINAPI myfun1(LPVOID lpParameter);	//声明线程函数
DWORD WINAPI myfun2(LPVOID lpParameter);
CCriticalSection m_Sec;									//定义全局变量m_Sec
int a=0;
												//定义全局变量a
int main()
{	
	HANDLE h1,h2;											//定义线程句柄
	h1=::CreateThread(NULL,0,myfun1,NULL,0,NULL);			//创建线程1
	printf("线程1开始运行!\r\n");
	h2=::CreateThread(NULL,0,myfun2,NULL,0,NULL);			//创建线程2
	printf("线程2开始运行!\r\n");
	::CloseHandle(h1);										//关闭线程句柄对象
	::CloseHandle(h2);
	::Sleep(10000);											//程序睡眠10秒
	return 0;
}
DWORD WINAPI myfun1(LPVOID lpParameter) 				//线程函数1
{
	m_Sec.Lock();										//锁定临界区
	a+=1;													//变量加1
	printf("%d\n",a);										//输出变量
	m_Sec.Unlock();								//对临界区进行解锁
	return 0;
}
DWORD WINAPI myfun2(LPVOID lpParameter) 		//线程函数2
{
	m_Sec.Lock();								//锁定临界区
	a+=1;											//变量加1
	printf("%d\n",a);								//输出变量
	m_Sec.Unlock();								//对临界区进行解锁
	return 0;
}

 

4. MFC事件对象

#include <afxmt.h>
#include <stdio.h>

DWORD WINAPI myfun1(LPVOID lpParameter);//声明线程函数
DWORD WINAPI myfun2(LPVOID lpParameter);
CEvent event(false,false,NULL,NULL);			//将事件对象定义为全局变量
int a=0;										//定义全局变量a

int main()
{	
	HANDLE h1,h2;									//定义线程句柄
	event.SetEvent();
	h1=::CreateThread(NULL,0,myfun1,NULL,0,NULL);	//创建线程1
	printf("线程1开始运行!\r\n");
	h2=::CreateThread(NULL,0,myfun2,NULL,0,NULL);	//创建线程2
	printf("线程2开始运行!\r\n");
	::CloseHandle(h1);								//关闭线程句柄对象
	::CloseHandle(h2);
	::Sleep(10000);									//程序睡眠10秒
	return 0;
}

DWORD WINAPI myfun1(LPVOID lpParameter) 		//线程函数1
{
	while(1)
	{
		::WaitForSingleObject(event.m_hObject,INFINITE);	//请求事件对象
		//event.ResetEvent();							//设置事件对象为无信号状态
		if(a<10000)
		{
			a+=1;											//变量自加
			::Sleep(1000);									//线程睡眠1秒
			printf("线程1:%d\r\n",a);					//输出变量
			event.SetEvent();							//设置事件对象为有信号状态
		}
		else
		{
			event.SetEvent();								//设置事件对象为有信号状态
			break;										//跳出循环
		}
	}
    return 0;									//线程
}
DWORD WINAPI myfun2(LPVOID lpParameter) 		//线程函数2
{
	while(1)
	{
		::WaitForSingleObject(event.m_hObject,INFINITE);	//请求事件对象
		//event.ResetEvent();							//设置事件对象为无信号状态
		if(a<10000)
		{
			a+=1;
			::Sleep(1000);
			printf("线程2:%d\r\n",a);					//输出变量
			event.SetEvent();
		}
		else
		{
			event.SetEvent();							//设置事件对象为有信号状态
			break;										//跳出循环
		}
	}
    return 0;									//线程正常退出
}

 

5. 线程间互斥对象

#include <windows.h>							//包含头文件
#include <stdio.h>

DWORD WINAPI myfun1(LPVOID lpParameter);//声明线程函数
DWORD WINAPI myfun2(LPVOID lpParameter);
HANDLE hmutex;
int a=0;										//定义全局变量a

int main()
{	
	hmutex=::CreateMutex(NULL,FALSE,NULL);			//创建互斥对象并返回其句柄
	HANDLE h1,h2;									//定义线程句柄
	h1=::CreateThread(NULL,0,myfun1,NULL,0,NULL);	//创建线程1
	printf("线程1开始运行!\r\n");
	h2=::CreateThread(NULL,0,myfun2,NULL,0,NULL);	//创建线程2
	printf("线程2开始运行!\r\n");
	::CloseHandle(h1);								//关闭线程句柄对象
	::CloseHandle(h2);
	::Sleep(10000);									//程序睡眠10秒
	return 0;
}

DWORD WINAPI myfun1(LPVOID lpParameter) 		//线程函数1
{
	while(1)
	{
		::WaitForSingleObject(hmutex,INFINITE);		//请求互斥对象
		if(a<10000)
		{
			a+=1;											//变量自加
			::Sleep(1000);									//线程睡眠1秒
			printf("线程1:%d\r\n",a);
			::ReleaseMutex(hmutex);						//释放互斥对象句柄
		}
		else
		{
			::ReleaseMutex(hmutex);							//释放互斥对象句柄
			break;										//跳出循环
		}
	}
    return 0;								
}
DWORD WINAPI myfun2(LPVOID lpParameter) 		//线程函数2
{
	while(1)
	{
		::WaitForSingleObject(hmutex,INFINITE);		//请求互斥对象
		if(a<10000)
		{
			a+=1;
			::Sleep(1000);
			printf("线程2:%d\r\n",a);					//输出变量
			::ReleaseMutex(hmutex);						//释放互斥对象句柄
		}
		else
		{	
			::ReleaseMutex(hmutex);						//释放互斥对象句柄
			break;										//跳出循环
		}
	}
    return 0;									//线程正常退出
}

 

6. 进程间互斥对象

#include<windows.h>								//包含头文件
#include<stdio.h>

int main()												//主函数
{
	HANDLE hmutex;									//定义互斥对象句柄
	hmutex=::CreateMutex(NULL,true,"VC网络编程");	//创建互斥对象并返回其句柄
	if(hmutex)										//判断创建互斥对象是否成功
	{
		if(ERROR_ALREADY_EXISTS==GetLastError())		//获取错误
		{
			printf("只允许一个实例程序运行!\r\n");		//打印相关信息
		}
		else
		{
			printf("实例程序运行成功!\r\n");
		}
	}
	::ReleaseMutex(hmutex);						//释放互斥对象句柄
	::Sleep(100000);								//使程序睡眠100秒
	return 0;										//程序正常结束
}

7. 临界区对象

#include <windows.h>							//包含头文件
#include <stdio.h>

DWORD WINAPI myfun1(LPVOID lpParameter );//声明线程函数
DWORD WINAPI myfun2(LPVOID lpParameter );

static int a1=0;								//定义全局变量并初始化
CRITICAL_SECTION Section;						//定义临界区对象

int main()										//主函数
{

	InitializeCriticalSection(&Section); 			//初始化临界区对象

	HANDLE h1,h2;									//定义线程句柄
	h1=::CreateThread(NULL,0,myfun1,NULL,0,NULL);	//创建线程1
	printf("线程1开始运行!\r\n");
	h2=::CreateThread(NULL,0,myfun2,NULL,0,NULL);	//创建线程2
	printf("线程2开始运行!\r\n");
	::CloseHandle(h1);								//关闭线程句柄对象
	::CloseHandle(h2);

	::Sleep(10000);									//程序睡眠10秒
	printf("正常退出程序请按\r\n");
	while(1)
	{
		if(getchar()=='q')								//如果用户输入字符q
		{
			DeleteCriticalSection(&Section);			//删除临界区对象
			return 0;
		}
	}
}

DWORD WINAPI myfun1(LPVOID lpParameter) 		//线程函数1
{
	while(1)							
	{
		EnterCriticalSection(&Section);			//进入临界区
		a1++;										//变量自加
		if(a1<10000)								//设置变量a1小于10000
		{
			//::Sleep(1000);								//程序睡眠1秒
			printf("线程1正在计数%d\r\n",a1);
			LeaveCriticalSection(&Section);				//离开临界区
		}
		else										//如果变量大于10000
		{
			LeaveCriticalSection(&Section);			//离开临界区
			break;									//跳出循环
		}
	}
	return 0;
}
DWORD WINAPI myfun2(LPVOID lpParameter) 		//线程函数2
{
	while(1)
	{
		EnterCriticalSection(&Section);		//进入临界区
		a1++;
		if(a1<10000)
		{
			//::Sleep(1000);							//程序睡眠1秒
			printf("线程2正在计数%d\r\n",a1);
			LeaveCriticalSection(&Section);				//离开临界区
		}
		else
		{
			LeaveCriticalSection(&Section);			
			break;
		}
	}
	return 0;									//线程函数返回0
}

 

8. 事件对象用于线程保护

 

 

#include <windows.h>							//包含头文件
#include <stdio.h>

DWORD WINAPI myfun1(LPVOID lpParameter);//声明线程函数
DWORD WINAPI myfun2(LPVOID lpParameter);
HANDLE hevent;									//定义全局变量hevent
int a=0;										//定义全局变量a

int main()
{	
	HANDLE h1,h2;									//定义线程句柄
	hevent=::CreateEvent(NULL,false,false,NULL);
	::SetEvent(hevent);
	h1=::CreateThread(NULL,0,myfun1,NULL,0,NULL);	//创建线程1
	printf("线程1开始运行!\r\n");
	h2=::CreateThread(NULL,0,myfun2,NULL,0,NULL);	//创建线程2
	printf("线程2开始运行!\r\n");
	::CloseHandle(h1);								//关闭线程句柄对象
	::CloseHandle(h2);
	::Sleep(10000);									//程序睡眠10秒
	return 0;
}

DWORD WINAPI myfun1(LPVOID lpParameter) 		//线程函数1
{
	while(1)
	{
		::WaitForSingleObject(hevent,INFINITE);		//请求事件对象
		if(a<10000)
		{
			a+=1;											//变量自加
			::Sleep(1000);									//线程睡眠1秒
			printf("线程1:%d\r\n",a);					//输出变量
			::SetEvent(hevent);							//设置事件对象为有信号状态
		}
		else
		{
			::SetEvent(hevent);							//设置事件对象为有信号状态
			break;										//跳出循环
		}
	}
    return 0;	
}
DWORD WINAPI myfun2(LPVOID lpParameter) 		//线程函数2
{
	while(1)
	{
		::WaitForSingleObject(hevent,INFINITE);		//请求事件对象
		if(a<10000)
		{
			a+=1;
			::Sleep(1000);
			printf("线程2:%d\r\n",a);					//输出变量
			::SetEvent(hevent);
		}
		else
		{
			::SetEvent(hevent);							//设置事件对象为有信号状态
			break;										//跳出循环
		}
	}
    return 0;									//线程正常退出
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值