zoukankan      html  css  js  c++  java
  • c++多线程编程(三)

    关于WaitForSingleObject函数用法 :

    用户模式的线程同步机制效率高,如果需要考虑线程同步问题,应该首先考虑用户模式的线程同步方法。
      但是,用户模式的线程同步有限制,对于多个进程之间的线程同步,用户模式的线程同步方法无能为力。这时,只能考虑使用内核模式。

      Windows提供了许多内核对象来实现线程的同步。对于线程同步而言,这些内核对象有两个非常重要的状态:“已通知”状态,“未通知”状态 (也有翻译为:受信状态,未受信状态)。Windows提供了几种内核对象可以处于已通知状态和未通知状态:进程、线程、作业、文件、控制台输入/输出 /错误流、事件、等待定时器、信号量、互斥对象。

      你可以通知一个内核对象,使之处于“已通知状态”,然后让其他等待在该内核对象上的线程继续执行。你可以使用Windows提供的API函数,等待函数来等待某一个或某些内核对象变为已通知状态。

      你可以使用WaitForSingleObject函数来等待一个内核对象变为已通知状态:

    DWORD WaitForSingleObject(
    HANDLE hObject, //指明一个内核对象的句柄
    DWORD dwMilliseconds); //等待时间
      该函数需要传递一个内核对象句柄,该句柄标识一个内核对象,如果该内核对象处于未通知状态,则该函数导致线程进入阻塞状态;如果该内核对象处于已通知 状态,则该函数立即返回WAIT_OBJECT_0。第二个参数指明了需要等待的时间(毫秒),可以传递INFINITE指明要无限期等待下去,如果第二 个参数为0,那么函数就测试同步对象的状态并立即返回。如果等待超时,该函数返回WAIT_TIMEOUT。如果该函数失败,返回 WAIT_FAILED。可以通过下面的代码来判断:

    DWORD dw = WaitForSingleObject(hProcess, 5000); //等待一个进程结束
    switch (dw)
    {
    case WAIT_OBJECT_0:
    // hProcess所代表的进程在5秒内结束
    break;

    case WAIT_TIMEOUT:
    // 等待时间超过5秒
    break;

    case WAIT_FAILED:
    // 函数调用失败,比如传递了一个无效的句柄
    break;
    }
      
    还可以使用WaitForMulitpleObjects函数来等待多个内核对象变为已通知状态:

    DWORD WaitForMultipleObjects(
    DWORD dwCount, //等待的内核对象个数
    CONST HANDLE* phObjects, //一个存放被等待的内核对象句柄的数组
    BOOL bWaitAll, //是否等到所有内核对象为已通知状态后才返回
    DWORD dwMilliseconds); //等待时间
      该函数的第一个参数指明等待的内核对象的个数,可以是0到MAXIMUM_WAIT_OBJECTS(64)中的一个值。phObjects参数是一 个存放等待的内核对象句柄的数组。bWaitAll参数如果为TRUE,则只有当等待的所有内核对象为已通知状态时函数才返回,如果为FALSE,则只要 一个内核对象为已通知状态,则该函数返回。第四个参数和WaitForSingleObject中的dwMilliseconds参数类似。

      该函数失败,返回WAIT_FAILED;如果超时,返回WAIT_TIMEOUT;如果bWaitAll参数为TRUE,函数成功则返回WAIT_OBJECT_0,如果bWaitAll为FALSE,函数成功则返回值指明是哪个内核对象收到通知。

      可以如下使用该函数:

    HANDLE h[3]; //句柄数组

    //三个进程句柄
    h[0] = hProcess1;
    h[1] = hProcess2;
    h[2] = hProcess3;

    DWORD dw = WaitForMultipleObjects(3, h, FALSE, 5000); //等待3个进程结束

    switch (dw)
    {
    case WAIT_FAILED:
    // 函数呼叫失败
    break;

    case WAIT_TIMEOUT:
    // 超时
    break;

    case WAIT_OBJECT_0 + 0:
    // h[0](hProcess1)所代表的进程结束
    break;

    case WAIT_OBJECT_0 + 1:
    // h[1](hProcess2)所代表的进程结束
    break;

    case WAIT_OBJECT_0 + 2:
    // h[2](hProcess3)所代表的进程结束
    break;
    }
      
    你也可以同时通知一个内核对象,同时等待另一个内核对象,这两个操作以原子的方式进行:

    DWORD SignalObjectAndWait(
    HANDLE hObjectToSignal, //通知的内核对象
    HANDLE hObjectToWaitOn, //等待的内核对象
    DWORD dwMilliseconds, //等待的时间
    BOOL bAlertable); //与IO完成端口有关的参数,暂不讨论
      该函数在内部使得hObjectToSignal参数所指明的内核对象变成已通知状态,同时等待hObjectToWaitOn参数所代表的内核对象。dwMilliseconds参数的用法与WaitForSingleObject函数类似。
      该函数返回如下:WAIT_OBJECT_0,WAIT_TIMEOUT,WAIT_FAILED,WAIT_IO_COMPLETION。

      等你需要通知一个互斥内核对象并等待一个事件内核对象的时候,可以这么写:

    ReleaseMutex(hMutex);
    WaitForSingleObject(hEvent, INFINITE);
      可是,这样的代码不是以原子的方式来操纵这两个内核对象。因此,可以更改如下:

    SignalObjectAndWait(hMutex, hEvent, INFINITE, FALSE);

  • 相关阅读:
    hdu1238 Substrings
    CCF试题:高速公路(Targin)
    hdu 1269 迷宫城堡(Targin算法)
    hdu 1253 胜利大逃亡
    NYOJ 55 懒省事的小明
    HDU 1024 Max Sum Plus Plus
    HDU 1087 Super Jumping! Jumping! Jumping!
    HDU 1257 最少拦截系统
    HDU 1069 Monkey and Banana
    HDU 1104 Remainder
  • 原文地址:https://www.cnblogs.com/jiu0821/p/5255352.html
Copyright © 2011-2022 走看看