#include<windows.h>
#include<iostream>
using namespace std;
DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);
int index = 0;
int tickets = 100;
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);
Sleep(4000);
}
DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
while(TRUE)
{
if (tickets>0)
{
cout<<"thread1 sell ticket:"<<tickets--<<endl;
}else
{
break;
}
}
return 0;
}
DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
while(TRUE)
{
if (tickets>0)
{
cout<<"thread2 sell ticket:"<<tickets--<<endl;
}else
{
break;
}
}
return 0;
}
上述程序出现一问题,就是两个线程访问了同一个全局变量:tickets。为了避免这种问题的发生,就要求在多个线程之间进行一个同步处理,保证一个线程访问共享资源时,其它线程不能访问该资源。必须等到前者完成火车票的销售过程之后,其他线程才能访问该资源。
利用互斥对象实现线程同步。
互斥对象属于内核对象,它能够确保线程拥有对单个资源的互斥访问权。互斥对象包含一个使用数量,一个线程ID和一个计数器。其中ID用于标识系统中的哪个线程当前拥有互斥对象,计数器用于指明该线程拥有互斥对象的次数。创建互斥对象函数:
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,//指向LPSECURITY_ATTRIBUTES的指针,可以传递NULL
BOOL bInitialOwner,//指定互斥对象初始的拥有者。为真时,则创建这个互斥对象的线程获得该对象的所有权,否则,该线程将不获得所创建的互斥对象的所有权
LPCTSTR lpName);//指定互斥对象的名称。如果此参数为NULL,则创建一个匿名的互斥对象
该函数可以创建或打开一个命名或匿名的互斥对象,然后程序就可以利用该互斥对象完成线程间的同步,如果调用成功,该函数返回所创建的互斥对象的句柄。如果创建的是命名的互斥对象,并且在CreateMutex函数调用之前,该命名的互斥对象存在,那么该函数将返回已经存在的这个互斥对象的句柄,而这时调用GetLastError函数将返回ERROR_ALREADY_EXISTS.另外,当线程对共享资源访问结束后,应释放该对象的所有权,也就是让该对象处于已通知状态。这时需要调用ReleaseMutex函数,该函数将释放指定对象的所有权,
BOOL ReleaseMutex(HANDLE hMutex)//hMutex为需要释放的互斥对象的句柄,调用成功,返回非0值,否则返回0值
另外,线程必须主动请求共享对象的使用权才有可能获得该所有权,这可以通过调用WaitForSingleObject函数来实现
DWORD WaitForSingleObject(HANDLE hHandle,//所请求的对象的句柄,一旦互斥对象处于有信号状态,刚该函数返回。否则,该函数会一直等待,这样就会暂停线程的执行
DWORD dwMilliseconds)//指定等待的时间间隔,以毫秒为单位。如果指定的时间间隔已过,即使所请求的对象仍处于无信号状态,WaitForSingleObject函数也会返回,如果将此参数设置为0,那么WaitForSingleObject函数将测试该对象的状态并立即返回;如果将此参数设置为INFINITE,则该函数会永远等待,直到等待的对象处于有信号状态才会返回
调用WaitForSingleObject函数后,该函数会一直等待,只有在以下两种情况下才会返回:
指定的对象变成有信号状态
指定的等待时间间隔已过
如果函数调用成功,那么WaitForSingleObject函数的返回值将表明引起该函数返回的事件
WAIT_OBJECT_0 所请求的对象是有信号状态
WAIT_TIMEOUT 指定的时间间隔已过,并且所请求的对象是无信号状态
WAIT_ABANDONED 所请求的对象是一个互斥对象,并且先前拥有该对象的线程在终止前没有释放该对象。这时,该对象的所有权将授予当前调用线程,并且将该互斥对象被设置为无信号状态
#include<windows.h>
#include<iostream>
using namespace std;
DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);
int tickets = 100;
HANDLE hMetex;
void main()
{
HANDLE hThread1;
HANDLE hThread2;
hThread1 = CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
Sleep(10);
hThread2 = CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
hMetex = CreateMutex(NULL,TRUE,NULL);
ReleaseMutex(hMetex);
Sleep(4000);
}
DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
while(TRUE)
{
WaitForSingleObject(hMetex,INFINITE);
if (tickets>0)
{
cout<<"thread1 sell ticket:"<<tickets--<<endl;
Sleep(10);
}else
{
break;
}
ReleaseMutex(hMetex);
}
return 0;
}
DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
while(TRUE)
{
WaitForSingleObject(hMetex,INFINITE);
if (tickets>0)
{
cout<<"thread2 sell ticket:"<<tickets--<<endl;
Sleep(10);
}else
{
break;
}
ReleaseMutex(hMetex);
}
return 0;
}