C++线程同步

C++线程同步的四种方式


1. mutex 互斥
2.event 事件
3.Critial Sections 临界区域
4.Semaphone 信号量
1. mutex 互斥
函数原型:
HANDLE CreateMutex(
	LPSECURITY_ATTRIBUTES lpMutexAttributes, // pointer to security attributes
	BOOL bInitialOwner,  // flag for initial ownership
  	LPCTSTR lpName       // pointer to mutex-object name
     );
	
HANDLE hMutex; //定义互斥hMutex;
hMutex=CreateMutex(NULL,FALSE,NULL);  //main函数创建互斥hMuntex;
WaitForSingleObject(hMutex,INFINITE);//函数实现部分获取互斥hMuntex的所有权;
ReleaseMutex(hMutex);//释放所有权;
//
实例:
#include<Windows.h>
#include<iostream>
using namespace std;
DWORD WINAPI Fun1Proc(
LPVOID lpParameter //thread data;
);
DWORD WINAPI Fun2Proc(
LPVOID lpParameter //thread data;
);
int index=0;
int tickets=100;
HANDLE hMutex;
void main()
{
HANDLE hThread1;
HANDLE hThread2;
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
hMutex=CreateMutex(NULL,FALSE,NULL);
Sleep(4000);
//system("pause");
}
     DWORD WINAPI Fun2Proc( LPVOID lpParameter  )
{
while(1)
{
WaitForSingleObject(hMutex,INFINITE);
if(tickets>0)
{
Sleep(1);
cout<<"Thread1 sell ticket :"<<tickets--<<endl;
}
else 
break;
ReleaseMutex(hMutex);
}
return 0;
}
DWORD WINAPI Fun2Proc( LPVOID lpParameter )
{
while(1)
{
WaitForSingleObject(hMutex,INFINITE);
if(tickets>0)
{
Sleep(1);
cout<<"Thread2 sell ticket :"<<tickets--<<endl;
}
else 
break;
ReleaseMutex(hMutex);
}
return 0;
}   
///
2.event 事件
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset, 
BOOL bInitialState,
LPCSTR lpName
);
bManualReset:TRUE,使用ResetEvent()手动重置为无信号状态;FALSE,当一个等待线程被释放时,自动重置状态为无信号状态。
bInitialState:指定事件对象的初始状态,当TRUE,初始状态为有信号状态;当FALSE,初始状态为无信号状态。
///
实例:
#include<Windows.h>
#include<iostream>
using namespace std;

DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);

int index=0;
int tickets=100;
HANDLE hEvent;
void main()
{
HANDLE hThread1;
HANDLE hThread2;
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);

hEvent=CreateEvent(NULL,0,FALSE,NULL);
//确保只有一个实例运行;
if(hEvent)
{
if(ERROR_ALREADY_EXISTS==GetLastError())
{
cout<<"Only one instance can run !";
return ;
}
}
SetEvent(hEvent);
Sleep(4000);
system("pause");
}

DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
while(1)
{
WaitForSingleObject(hEvent,INFINITE);
if(tickets>0)
{
Sleep(1);
cout<<"Thread1 sell ticket :"<<tickets--<<endl;
}
else 
break;
SetEvent(hEvent);
}
return 0;
}

DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
while(1)
{
WaitForSingleObject(hEvent,INFINITE);
if(tickets>0)
{
Sleep(1);
cout<<"Thread2 sell ticket :"<<tickets--<<endl;
}
else 
break;
SetEvent(hEvent);
}
return 0;
}   

3.Critial Sections 临界区域

工作在用户方式下,它是指一个小代码段,在代码能够执行前,它必须独占对某些资源的访问权,通常把多线程访问同一种资源的那部分代码当作关键代码段.

VOID InitializeCriticalSection(//初始化代码段

 LPCRITICAL_SECTIONlpCriticalSection //[out] critical section,使用之前要构造

);

VOID EnterCriticalSection(//进入关键代码段(临界区)

 LPCRITICAL_SECTIONlpCriticalSection // critical section

);

VOID LeaveCriticalSection(//离开关键代码段(临界区)

 LPCRITICAL_SECTIONlpCriticalSection   // critical section

);

VOID DeleteCriticalSection(//删除关键代码段(临界区)

 LPCRITICAL_SECTIONlpCriticalSection   // critical section

);

种方法比较简单!但缺点是如果使用了多少关键代码码,容易赞成线程的死锁(使用两个或以上的临界区对象或互斥对象,造成线程1拥有了临界区对象A,等待临界区对象B的拥有权,线程2拥有了临界区对象B,等待临界区对象A的拥有权,形成死锁,程序无法执行下去!


        注意:不要使临界区一直处于未释放的状态;
    虽然临界区同步速度比较快,但是只能用来同步本进程内的线程,而不能跨进程同步。
    MFC中,有一个CCriticalSection类,此类中有两个方法Lock和UnLock,只需要在需要同步的代码前后加入这两个函数,    就可以实现临界区资源。
//
实例:  
#include<Windows.h>
#include<iostream>
using namespace std;

DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);

int index=0;
int tickets=100;
CRITICAL_SECTION g_cs;//构造全局临界区对象;
void main()
{
HANDLE hThread1;
HANDLE hThread2;
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
InitializeCriticalSection(&g_cs);//初始化对象;
Sleep(4000);
DeleteCriticalSection(&g_cs);//程序结束时释放临界区对象所有资源;
system("pause");
}

DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
while(1)
{
EnterCriticalSection(&g_cs);//判断是否得到临界区对象所有权;
if(tickets>0)
{
Sleep(1);
cout<<"Thread1 sell ticket :"<<tickets--<<endl;
}
else 
break;
LeaveCriticalSection(&g_cs);//释放临界区对象所有权;
}
return 0;
}


DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
while(1)
{
EnterCriticalSection(&g_cs);
if(tickets>0)
{
Sleep(1);
cout<<"Thread2 sell ticket :"<<tickets--<<endl;
}
else 
break;
LeaveCriticalSection(&g_cs);
}
return 0;
}   
///
4.Semaphone 信号量


~~~~~~~~~~~~~~~~~~~~~~~~~~待续~~~~~~~~~~~~~~~~~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值