【问题标题】:LeaveCriticalSection() yieldLeaveCriticalSection() 产量
【发布时间】:2013-09-26 07:14:29
【问题描述】:

我有两个线程共享一个临界区。线程 A 永久保持对临界区的锁定,但每秒运行大约 50 次以下代码,以使线程 B 有机会介入:

LeaveCriticalSection(sec);
EnterCriticalSection(sec);

但是,使用此代码,线程 B 似乎永远没有机会获得临界区。相反,线程 B 中对 EnterCriticalSection(sec) 的调用将永远阻塞该线程,尽管线程 A 每秒解锁临界区 50 次。

我知道在线程 A 中的 50hz 计时器中调用 LeaveCriticalSection() 和 EnterCriticalSection() 之间的时间间隔尽可能短,但我希望 LeaveCriticalSection() 调用能够让其他线程等待继续执行之前的关键部分。

LeaveCriticalSection() 不应该这样工作吗?如果是这样,有没有办法在释放临界区锁后显式让步给其他线程? POSIX 有类似 sched_yield() 的东西,但我认为在 POSIX 上什至没有必要,因为 pthread_mutex_unlock() 会给其他线程一个自动介入的机会。

但它似乎在 Windows 上不起作用(或者我的代码有问题)。任何人都可以对此有所了解吗?

谢谢!

【问题讨论】:

标签: multithreading winapi posix


【解决方案1】:

线程 A 可能需要通过 Sleep(0) 或类似调用来产生其时间片。临界区操作通常停留在用户模式代码中,因此它们不会转换到内核,因此不会放弃线程 A 的时间片。

【讨论】:

  • 好的,插入 Sleep(0) 有帮助,但不是可接受的方式,因为线程 B 需要几秒钟才能获取临界区,尽管它在线程 A 中每秒解锁 50 次。是否有另一种强制立即收益的方法?
  • 要真正保证他们按照您想要的方式传递,您需要使用诸如互斥锁之类的内核对象,或者使用事件建立信号机制。
  • 确实,因为由于其他线程没有获得内核对象的特权(优先级提升意味着立即唤醒),它唯一有机会获得临界区的时间是如果有Leave() 和 Enter() 之间的上下文切换。
【解决方案2】:

如果您想在如此紧密的循环中让步,您可能可以使用mutex 而不是关键部分来实现(免责声明:我尚未验证)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-29
    • 2012-07-13
    • 2016-08-25
    • 1970-01-01
    • 2016-06-08
    • 2015-11-14
    • 2018-02-04
    • 2014-03-02
    相关资源
    最近更新 更多