• Windows编程--线程和内核对象的同步-信标(信号量)内核对象


    信标内核对象用于对资源进行计数。它们与所有内核对象一样,包含一个使用数量,但是它们也包含另外两个带符号的3 2位值

    一个是最大资源数量,用于标识信标能够控制的资源的最大数量

    一个是当前资源数量,用于标识当前可以使用的资源的数量

    (FangSH注:有些书称之为信息量内核对象)

    为了正确地说明这个问题,让我们来看一看应用程序是如何使用信标的。比如说,我正在开发一个服务器进程,在这个进程中,我已经分配了一个能够用来存放客户机请求的缓冲区。我对缓冲区的大小进行了硬编码,这样它每次最多能够存放5个客户机请求。如果5个请求尚未处理完毕时,一个新客户机试图与服务器进行联系,那么这个新客户机的请求就会被拒绝,并出现一个错误,指明服务器现在很忙,客户机应该过些时候重新进行联系。

    当我的服务器进程初始化时,它创建一个线程池,里面包含5个线程,每个线程都准备在客户机请求到来时对它进行处理。

    开始时,没有客户机提出任何请求,因此我的服务器不允许线程池中的任何线程成为可调度线程。但是,如果3个客户机请求同时到来,那么线程池中应该有3个线程处于可调度状态。使用信标,就能够很好地处理对资源的监控和对线程的调度,最大资源数量设置为5,因为这是我进行硬编码的缓冲区的大小。当前资源数量最初设置为0,因为没有客户机提出任何请求。当客户机的请求被接受时,当前资源数量就递增,当客户机的请求被提交给服务器的线程池时,当前资源数量就递减。

    信标的使用规则如下:

    • 如果当前资源的数量大于0,则发出信标信号。

    • 如果当前资源数量是0,则不发出信标信号。

    • 系统决不允许当前资源的数量为负值。

    • 当前资源数量决不能大于最大资源数量。

     注意

    当使用信标时,不要将信标对象的使用数量与它的当前资源数量混为一谈。

    下面的函数用于创建信标内核对象:

    HANDLE CreateSemaphore(
    PSECURITY_ATTRIBUTE psa,
    // 安全属性指针
    LONG lInitialCount, //当前可用资源初始值,这个值必须大于等于0,小于等于lMaximumCount
    LONGlMaximumCount, //最大可用的资源数,这个值必须大于0
    PCTSTRpszName); //对象名指针

    Psa和pszName两个参数内核对象的安全属性和,内核对象的命名。

    MaximumCount参数用于告诉系统,应用程序处理的最大资源数量是多少。由于这是个带符号的32位值,因此最多可以拥有2 147 483 647个资源。

    lInitialCount参数用于指明开始时(当前)这些资源中有多少可供使用。

    通过调用OpenSemaphore函数,另一个进程可以获得它自己的进程与现有信标相关的句柄

    HANDLE OpenSemaphore(
    DWORDfdwAccess,
    BOOL bInheritHandle,
    PCTSTRpszName);

    当我的服务器进程初始化时,没有任何客户机请求,因此我调用下面这个CreateSemaph ore函数:

    HANDLE hsem =CreateSemaphore(NULL, 0, 5, NULL);

    该函数创建了一个信标,其最大资源数量为5,但是开始时可以使用的资源为0因此不发出信标信号。等待信标的所有线程均进入等待状态。

     (FangSH注:资源的访问,当前可用资源计数就会减1,只要当前可用资源计数是大于0的,就可以发出信号量信号。
    但是当前可用计数减小到0时则说明当前占用资源的线程数已经达到了所允许的最大数目,不能在允许其他线程的进入
    此时的信号量信号将不发出信标信号.

    )

    通过调用ReleaseSemaphore函数,线程就能够对信标的当前资源数量进行递增

    BOOL ReleaseSemaphore(
    HANDLE hsem,
    //信号量句柄
    LONGlReleaseCount, // 计数递增数量
    PLONGplPreviousCount); // 先前计数

    该函数只是将lReleaseCount 中的值添加给信标的当前资源数量。一般情况下,为lReleaseCount参数传递1。但是,不一定非要传递这个值。我常常传递2或更大的值。该函数也能够在它的* plPreviousCount中返回当前资源数量的原始值。实际上几乎没有应用程序关心这个值,因此可以传递NULL,将它忽略。

     

    总结:

    WaitForSingleObject()WaitForMultipleObjects()主要用在试图进入共享资源的线程函数入口处,主要用来判断信号量的当前可用资源计数是否允许本线程的进入。只有在当前可用资源计数值大于0时,被监视的信号量内核对象才会得到通知。

    函数CreateSemaphore的psa为NULL,lInitialCount为当前可用资源初始值,lMaximumCount为最大可用资源数,pszName为名字。当lInitialCount的值等于0时,信标对象处于无信号状态,这时内核将调用等待函数的线程置于睡眠状态,如果lInitialCount的值大于0,信标对象处于有信号状态,这时内核将调用等待函数的线程置于运行状态,并将信标对象的当前可用资源数减1

    函数ReleaseSemaphore的hsem为信标对象的句柄,lReleaseCount为要释放的资源数,plPreviousCount返回原来可用资源数,调用此函数将当前可用资源数加上lReleaseCount的值。当一个线程访问完可用资源后,应该调用ReleaseSemaphore函数使当前可用资源数递增。要在不同进程中访问同一信标对象,调用CreateSemaphore函数并传递信标对象的名称,得到已经在其它进程创建的信标对象的句柄。另外有一点要注意,等待函数默认将信标对象的当前可用资源数减1,但线程可能一次使用多个资源,这就可能出现问题了。为避免问题出现,应该遵守一个线程只使用一个资源的原则。

    FangSH 2011-01-04

  • 相关阅读:
    201521123069 《Java程序设计》 第13周学习总结
    201521123069 《Java程序设计》 第12周学习总结
    网络15软工个人作业5--软件工程总结
    个人作业4--alpha阶段个人总结
    软工网络15个人作业3——案例分析
    软件工程网络15结对编程作业1
    201521123004《软件工程》个人阅读作业2-提问题
    201521123004《软件工程》个人阅读作业1
    Java课程设计—学生成绩管理系统(201521123004-林艺如)
    201521123004 《Java程序设计》第 14 周学习总结
  • 原文地址:https://www.cnblogs.com/fangshenghui/p/1926764.html
Copyright © 2020-2023  润新知