• 火车站售票系统模拟程序


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

  • 相关阅读:
    top-adx-apps
    mac 打印机无法打印
    doubleclick-video-skipable
    微信小程序-基础学习
    uniapp-学习总结1
    react-1
    mysql-1
    jenkins-1
    后台管理系统-1
    微信小程序-父子组件通信
  • 原文地址:https://www.cnblogs.com/fenghuan/p/4863441.html
Copyright © 2020-2023  润新知