【问题标题】:using CONDITION_VARIABLE with mutex HANDLE将 CONDITION_VARIABLE 与互斥锁 HANDLE 一起使用
【发布时间】:2014-02-10 12:08:17
【问题描述】:

我正在尝试将我的一个 linux 项目移植到 Windows。

在项目中,我使用 pthread_cond_t,为了能够等待,需要一个 pthread_mutex_t。
它们都隐藏在不同的类中,它们的锁定/等待都应该支持 timedwait。
现在,在 linux 中,这一切都记录在案并且很容易,但是在 Windows 上,我没有找到任何文档,也没有任何与之相关的问题。

我知道有 CONDITION_VARIABLEs,但它们仅适用于 CRITICAL_SECTIONs,根据 Windows 文档无法定时等待,当然还有 CONDITION_VARIABLEs 不能使用的 HANDLE mutex。

我不想使用任何 boost 或 ace 内置对象或任何东西,我正在寻找纯操作系统功能。

这里有什么我遗漏的吗?

【问题讨论】:

  • SleepConditionVariableCS 需要超时,相当于 pthread_cond_timedwait()。
  • 我知道,但是 CONDITION_VARIABLE 在一个类中,而 CRITICAL_SECTION 在一个类中,但 CRITICAL_SECTION 不能等待,这是必须的。

标签: c++ windows mutex condition-variable


【解决方案1】:

在 linux 中,这一切都记录在案并且很容易 - 因为 Windows 中有更多的同步原语,而且命名也不同。

我找不到任何文档 - 我会从 with this article 开始,但要注意它只涵盖其中的一部分。 This list 涵盖了大约 50% 的最流行的原语。

“CONDITION_VARIABLEs,但它们仅适用于 CRITICAL_SECTION” - 也适用于 Slim 读取器/写入器 (SRW) 锁。

如果您想要更好的答案,您可能应该告诉我们您需要项目中同步原语的哪些功能。

附:如果您正在创建任何高性能和可扩展的东西,则根本不应该阻塞线程。很多时候,Windows 上最有效的多线程策略是从不等待任何同步原语,只等待用户/IO 子系统/网络/其他外部源。不过我明白,此类应用程序从一开始就应该这样设计,如果您从非 Windows 平台移植,这是不可能实现的。

更新: 出于研究目的(即,如果您不关心性能、延迟或电能),您可以轻松地在临界区对象上实现等待。请看示例代码(未经测试):

static const DWORD msSleepTime = 100; // default time to sleep waiting for the CS
bool WaitForCriticalSection( LPCRITICAL_SECTION lpCriticalSection, DWORD msTimeout )
{
    if( dwTimeout == INFINITE )
    {
        EnterCriticalSection( lpCriticalSection );
        return true;
    }

    while( true )
    {
        if( TryEnterCriticalSection( lpCriticalSection ) )
            return true;
        if( msTimeout <=0 )
            return false;
        DWORD msToSleepTime = std::min( msTimeout, msSleepTime );
        Sleep( msToSleepTime );
        msTimeout -= msToSleepTime;
    }
}

但是,对于任何生产质量体系,这种方法是不可接受的,应该使用不同的方法。您不能等待临界区或 SRW 锁有一个很好的理由:您不应该这样做。它们都是为轻量级用户模式线程同步而设计的。通常,您不应将它们锁定超过几毫秒。如果需要,这意味着使用临界区只是浪费 CPU 资源和电能,而应该使用例如互斥原语。

【讨论】:

  • 这是一个相当小的项目。移植主要用于 Windows 学习目的,我试图让 api 尽可能完整。我的主要问题是:是否有某种 CONDITION_VARIABLE 类和 MUTEX 类都可以等待并且 CONDITION_VARIABLE 使用 MUTEX 来锁定自己?
  • 非常感谢您的帮助!我试图避免忙于等待,但这种情况似乎别无选择。 :))
  • Sleep API 并没有真正忙于等待,它只是重新调度线程。在电能稀缺的移动环境中,只有每 100 毫秒唤醒一次以检查某些条件的线程才被认为是“忙于等待”。但是,它显然会带来额外的延迟(平均至少 50 毫秒)。
猜你喜欢
  • 2020-08-12
  • 1970-01-01
  • 1970-01-01
  • 2018-02-15
  • 2012-08-06
  • 2010-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多