首页 文章

信号量 - 初始计数有什么用?

提问于
浏览
64

http://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim.aspx

要创建信号量,我需要提供初始计数和最大计数 . MSDN声明初始计数是 -

可以同时授予的信号量的初始请求数 .

虽然它声明最大数量是

可以同时授予的信号量的最大请求数 .

我可以理解,最大计数是可以同时访问资源的最大线程数 . 但是,初始计数的用途是什么?

如果我创建一个初始计数为0且最大计数为2的信号量,则我的线程池线程都不能访问该资源 . 如果我将初始计数设置为1并将最大计数设置为2,则只有线程池线程可以访问该资源 . 只有当我将初始计数和最大计数都设置为2时,2个线程才能同时访问资源 . 那么,我真的很困惑初始计数的意义?

SemaphoreSlim semaphoreSlim = new SemaphoreSlim(0, 2); //all threadpool threads wait
SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 2);//only one thread has access to the resource at a time
SemaphoreSlim semaphoreSlim = new SemaphoreSlim(2, 2);//two threadpool threads can access the resource concurrently

7 回答

  • 1

    是的,当初始数字设置为0时 - 所有线程将在您增加“CurrentCount”属性时等待 . 您可以使用Release()或Release(Int32)来完成此操作 .

    释放(...) - 将增加信号量计数器

    等待(...) - 将减少它

    您不能递增计数器(“CurrentCount”属性)大于您在初始化中设置的最大计数 .

    例如:

    SemaphoreSlim^ s = gcnew SemaphoreSlim(0,2); //s->CurrentCount = 0
    s->Release(2); //s->CurrentCount = 2
    ...
    
    s->Wait(); //Ok. s->CurrentCount = 1
    ...
    
    s->Wait(); //Ok. s->CurrentCount = 0
    ...
    
    s->Wait(); //Will be blocked until any of the threads calls Release()
    
  • 44

    所以,我对初始计数的重要性感到困惑?

    这里可能有用的一个重点是 Wait 递减信号量计数, Release 递增它 .

    initialCount 是立即允许的资源访问次数 . 或者,换句话说,它是在实例化信号量后立即调用 Wait 而不立即阻塞的次数 .

    maximumCount 是信号量可以获得的最高计数 . 假设 initialCount count为零,则可以在不抛出异常的情况下调用 Release 的次数 . 如果 initialCount 设置为与 maximumCount 相同的值,则在实例化信号量后立即调用 Release 将引发异常 .

  • 0

    您希望一次能够访问资源多少个线程?将初始计数设置为该数字 . 如果该数字在程序的整个生命周期中永远不会增加,请将最大计数设置为该数字 . 这样,如果您在释放资源方面遇到编程错误,您的程序将崩溃并通知您 .

    (有两个构造函数:一个只接受初始值,另一个接受最大计数 . 使用适当的 . )

  • 5

    这样当当前线程创建信号量时,它可以从一开始就声明一些资源 .

  • 1

    如果您希望一段时间内没有线程访问您的资源,您将初始计数传递为0,并且当您希望在创建信号量后立即授予对所有这些资源的访问权限时,您将初始计数的值传递给最大计数 . 例如:

    hSemaphore = CreateSemaphoreA(NULL, 0, MAX_COUNT, NULL) ;
    
    //Do something here
    //No threads can access your resource
    
    ReleaseSemaphore(hSemaphore, MAX_COUNT, 0) ;
    
    //All threads can access the resource now
    

    正如MSDN文档中所引用的那样 - “ReleaseSemaphore的另一个用途是在应用程序初始化期间 . 应用程序可以创建初始计数为零的信号量 . 这会将信号量的状态设置为无信号并阻止所有线程访问受保护资源 . 完成初始化后,它使用ReleaseSemaphore将计数增加到其最大值,以允许正常访问受保护资源 . “

  • 57

    Semaphores can be used to protect a pool of resources . 我们使用资源池来重用 expensive to create 之类的东西 - 比如数据库连接 .

    因此,初始计数是指某个进程开始时池中可用资源的数量 . 当您阅读代码中的 initialCount 时,您应该考虑在创建此资源池时需要花费多少精力 .

    我对初始计数的重要性感到困惑?

    Initial count = Upfront cost

    因此,根据应用程序的使用情况,此值可能会对应用程序的性能产生巨大影响 . 这不仅仅是一些任意数字 .

    您应该仔细考虑您创建的内容,创建的成本以及您需要的数量 . 您应该能够绘制此参数的最佳值,并且应该考虑使其可配置,以便您可以将流程的性能调整到它的时间执行 .

  • 1

    正如MSDN在备注部分解释的那样:

    如果initialCount小于maximumCount,则效果与当前线程调用WaitOne(maximumCount减去initialCount)次数相同 . 如果您不想为创建信号量的线程保留任何条目,请对maximumCount和initialCount使用相同的数字 .

    因此,如果初始计数为0且max为2,则好像WaitOne已被主线程调用两次,因此我们已达到容量(信号量计数现在为0)并且没有线程可以进入信号量 . 类似地,如果初始计数为1且max为2,则一次调用WaitOnce,并且在我们再次达到容量之前只能有一个线程进入,依此类推 .

    如果0用于初始计数,我们总是可以调用Release(2)将信号量计数增加到max,以允许最大线程数获取资源 .

相关问题