【问题标题】:EventWaitHandle behavior for pthread_cond_tpthread_cond_t 的 EventWaitHandle 行为
【发布时间】:2010-09-13 16:07:09
【问题描述】:

我最近看到了 EventWaitHandle 在 C# 中的强大行为,并决定在姊妹应用程序中移动一些功能来做同样的事情。唯一的问题是姊妹应用程序是用 C 编写的。

没什么大不了的,我正在使用 pthreads,它有一个 pthread_cond_t 数据类型,允许发送信号。我唯一的问题是,是否有可能在等待它之前“发出信号”?

现在我的测试说不。也就是说,如果 ThreadA 在 ThreadB 等待之前触发了一个信号,那么 ThreadB 将无限期地等待。是否有另一种我可以使用的 pthread 类型更接近 C# 中 EventWaitHandle 的功能?一个对象是有信号的,这意味着第一个等待它的线程将立即通过,并将其设置为无信号。

将 pthread_cond 包装到另一个数据结构中不会太难实现这一点。但同样,这个功能是否已经在 pthread 库中可用?

【问题讨论】:

    标签: c# c multithreading data-structures pthreads


    【解决方案1】:

    如果你正确地使用了条件变量,这无关紧要。

    您的代码的基本流程应该是(在伪代码中):

    lock(lockobj);
    while (!signalled) {
        wait(condvar);
    }
    signalled = false;
    unlock(lockobj);
    

    在等待侧,并且:

    lock(lockobj);
    signalled = true;
    notify(condvar);
    unlock(lockobj);
    

    在信号方面。 (当然,两侧使用的锁对象和条件变量必须相同。)希望对您有所帮助!

    【讨论】:

    • 如果在发送信号之前等待线程被锁定,可能会导致死锁......不是吗?
    • 不,请记住,在等待 condvar 时,lockobj 会被释放(这是通过条件变量的工作方式自动和原子地完成的)。但是,它在等待线程重新执行之前重新获取。
    • 请参阅opengroup.org/onlinepubs/009695399/functions/… 了解互斥体释放行为。
    • nods 另外,请记住使用 while 循环而不是 if 语句进行检查。在极少数情况下(称为“虚假唤醒”,在上面 pthread_cond_wait 的链接中),您的等待线程会被外部环境唤醒。
    • 作为旁注,终于看到了pthreads的windows实现的源代码。 pthread_cond_t 是通过 windows 事件实现的!我猜我绕了一圈!
    【解决方案2】:

    如果您想要多个信号(即,如果发出两次信号,则两个线程可以在状态再次取消信号之前等待)的替代答案(也是伪代码)。

    等待方:

    lock(lockobj);
    while (signalled != 0) {
        wait(condvar);
    }
    --signalled;
    unlock(lockobj);
    

    信令端:

    lock(lockobj);
    ++signalled;
    notify(condvar);
    unlock(lockobj);
    

    【讨论】:

      【解决方案3】:

      我最终只是将一个条件类型包装在一个新结构中,并创建了一些简单的函数,其行为与 C# 中的 EventWaitHandle 非常相似。我需要两个互斥锁来实现正确的序列化访问。

      cond_mutex 用于等待条件变量,而 data_mutex 用于将状态从 signaled 设置为 not signaled。

      重置模式与 C# 相同。自动或手动。这允许 event_wait_t 在等待后自动重置。或者让程序员手动调用 event_wait_reset(event_wait_t *ewh);

      【讨论】:

      • 不,1 个互斥体就足够了。请参阅我的评论(关于 pthread_cond_wait 的互斥释放行为),了解为什么会这样。 (event_wait_reset 可以使用相同的互斥锁。)
      猜你喜欢
      • 2020-02-04
      • 2012-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多