首选使用临界区对象,主要原因是使用简单。
#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;
DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);
int tickets=100;
CRITICAL_SECTION g_csA;
CRITICAL_SECTION g_csB;
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_csA);
InitializeCriticalSection(&g_csB);
Sleep(40000);
DeleteCriticalSection(&g_csA);
DeleteCriticalSection(&g_csB);
}
DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
while (TRUE)
{
Sleep(100);
EnterCriticalSection(&g_csA);
//EnterCriticalSection(&g_csB); //临界区的同步和互锁
if(tickets>0)
{
Sleep(1);
cout<<"Thread1 sell ticket :"<<tickets--<<endl;
//LeaveCriticalSection(&g_csB);
LeaveCriticalSection(&g_csA);
}
else
{
//LeaveCriticalSection(&g_csB);
LeaveCriticalSection(&g_csA);
break;
}
}
return 0;
}
DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
while (TRUE)
{
Sleep(1);
EnterCriticalSection(&g_csB);
//EnterCriticalSection(&g_csA);
if(tickets>0)
{
Sleep(1);
cout<<"Thread2 sell ticket :"<<tickets--<<endl;
//LeaveCriticalSection(&g_csA);
LeaveCriticalSection(&g_csB);
}
else
{
//LeaveCriticalSection(&g_csA);
LeaveCriticalSection(&g_csB);
break;
}
}
return 0;
}
二、使用事件对象
#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;
DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);
int tickets=100;
HANDLE g_hEvent;
void main()
{
HANDLE hThread1;
HANDLE hThread2;
//**************************************************
// 创建一个命名的自动重置事件内核对象
g_hEvent=CreateEvent(NULL,FALSE,FALSE,LPCWSTR("tickets"));
if(g_hEvent)
{
if(ERROR_ALREADY_EXISTS==GetLastError())
{
cout<<"only _disibled event"<<endl;
}
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
SetEvent(g_hEvent);
Sleep(40000);
//关闭事件对象句柄
CloseHandle(g_hEvent);
}
}
DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
while (TRUE)
{
WaitForSingleObject(g_hEvent,INFINITE);
//ResetEvent(g_hEvent);
if(tickets>0)
{
Sleep(1);
cout<<"thread1 sell ticket :"<<tickets--<<endl;
SetEvent(g_hEvent);
}
else
{
SetEvent(g_hEvent);
break;
}
}
return 0;
}
DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
while (TRUE)
{
WaitForSingleObject(g_hEvent,INFINITE);
//ResetEvent(g_hEvent);
if (tickets>0)
{
cout<<"Thread2 sell ticket :"<<tickets--<<endl;
SetEvent(g_hEvent);
}
else
{
SetEvent(g_hEvent);
break;
}
}
return 0;
}
三、使用互斥对象
#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 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,TRUE,LPCWSTR("tickets")); // 创建时主线程拥有该互斥对象,互斥对象的线程ID为主线程的ID,同时将该互斥对象内部计数器置为1 if (hMutex) { if (ERROR_ALREADY_EXISTS==GetLastError()) { cout<<"only one instance can run!"<<endl; //Sleep(40000); return; } } //************************************************************** WaitForSingleObject(hMutex,INFINITE); // 使用该函数请求互斥对象时,虽说该对象处于无信号状态,但因为请求的线程ID和该互斥对象所有者的线程ID是相同的. //所以仍然可以请求到这 个互斥对象,于是该互斥对象内部计数器加1,内部计数器的值为2. ReleaseMutex(hMutex);//释放一次互斥对象,该互斥对 象内部计数器的值递减1,操作系统不会将这个互斥对象变为已通知状态. ReleaseMutex(hMutex);//释放一次互斥对象,该互 斥对象内部计数器的值为0,同时将该对象设置为已通知状态. //对于互斥对象来说,谁拥有谁释放 Sleep(40000); }DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{ while (TRUE) { WaitForSingleObject(hMutex,INFINITE);// 等待互斥对象有信号 if (tickets>0) { Sleep(1); cout<<"thread1 sell ticket :"<<tickets--<<endl; } else break; ReleaseMutex(hMutex);// 设置该互斥对象的线程ID为0,并且将该对象设置为有信号状态 } return 0; }DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{ while (TRUE) { WaitForSingleObject(hMutex,INFINITE); if (tickets>0) { Sleep(1); cout<<"thread2 sell ticket :"<<tickets--<<endl; } else break; ReleaseMutex(hMutex); } return 0; }