火车站售票系统模拟程序

#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;
}

posted @ 2015-10-09 11:22  fenghuan  阅读(2236)  评论(0编辑  收藏  举报