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>
#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;}elsebreak;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;}elsebreak;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;}elsebreak;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;}elsebreak;LeaveCriticalSection(&g_cs);}return 0;}///
4.Semaphone 信号量
~~~~~~~~~~~~~~~~~~~~~~~~~~待续~~~~~~~~~~~~~~~~~