【问题标题】:Is there a way to find out the current count of a win32 semaphore?有没有办法找出 win32 信号量的当前计数?
【发布时间】:2011-02-14 19:22:08
【问题描述】:

我正在寻找一种没有副作用的方法。

理想情况下,以下代码可以解决问题:

long currentCount = 0;  
::ReleaseSemaphore(h, 0, &currentCount);  

但遗憾的是,lReleaseCount 的值不允许为 0,因此调用返回 FALSE。

【问题讨论】:

    标签: winapi semaphore


    【解决方案1】:

    没有诸如 Win32 信号量的“当前计数”之类的东西 - 这就是您无法获得它的原因。

    我的意思是,显然,在某个时间点,信号量的计数将是某个值,但从线程的角度来看,除非它采取行动来增加或减少信号量计数,否则另一个线程可能会做出任何计算时检索到的答案完全无效。

    正是由于这个原因,windows api 同步功能不允许您在没有副作用的情况下获取先前的锁定计数。副作用保证您有一个有效的机会窗口以有意义的方式实际使用该值。


    明显的“解决方法”是做类似的事情

    LONG count = 0;
    if( WAIT_OBJECT_0 == WaitForSingleObject(hSemaphore,0L))
    {
      // Semaphores count is at least one.
      ReleaseSemaphore(hSemaphore,1,&count);
    }
    

    为什么这样更好?我不知道。但也许有可能在等待和释放之间做一些有意义的事情,如果允许 ReleaseSemaphore 释放 0,这将是一个竞争条件。

    【讨论】:

    • 这种能力对于外部监控很有用(例如生产者和消费者,其中信号量的计数表示仍待处理的对象的数量)。因此,我很惊讶它是可撤销的。
    • 解决方法的问题是它可能会扭曲您对信号量的实际使用;您可能会在将信号量用于预期目的的线程中引入等待。引入的等待将很小,但可能足以导致上下文切换。最好只维护自己的监控计数器。
    【解决方案2】:

    如果您希望该值用于外部监控(正如您在评论中所建议的那样),那么在调用 ReleaseSemaphore() 或恕我直言之后使用之前的值,一个更好的解决方案是您实现自己的“联锁”计数器,除了你的信号量;然后你就有了你的监控计数,并且可以以任何你喜欢的方式访问它......只是不要用它来查看你是否可以“输入”信号量......

    正如 Chris 所说,您无法获得当前计数,因为它可能一直在变化。

    【讨论】:

    • 如果在访问信号量之前将包装器的互锁解决方案替换为实际锁,则可以随意使用计数。
    【解决方案3】:

    sysinternals 工具 Process Explorer 可以显示 win32 句柄的内部结构,包括信号量及其当前/最大计数。对于调试来说已经足够了,但对于自动监控来说不是那么有用。

    如果 Process Explorer 可以做到,您可能也可以...但可能需要深入了解 Windows 内部结构。

    【讨论】:

      【解决方案4】:

      这可能有点太晚了,但我认为 NtQuerySemaphore() 可能是你想看看的。

      【讨论】:

        猜你喜欢
        • 2010-11-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-30
        • 1970-01-01
        • 1970-01-01
        • 2020-10-15
        相关资源
        最近更新 更多