【问题标题】:Signalling a particular thread among many waiting on a condition variable在许多等待条件变量的线程中向特定线程发出信号
【发布时间】:2011-08-28 20:12:47
【问题描述】:

这个问题来自Breaking a condition variable deadlock。许多线程可能正在等待条件变量,我只需要向特定线程发出信号,比如线程 1 并杀死它,因为它是死锁场景的参与者。有没有办法我可以在很多中只发出一个特定的线程。

不胜感激

谢谢

编辑;尊重 Nemo 的 cmets。我明白这是个坏主意。但是,有没有办法做到这一点

【问题讨论】:

  • 概率非常接近 1,您的设计存在缺陷。您几乎肯定想要“检测死锁并杀死参与其中的线程之一”。你想修复你的基本设计,这样死锁就不会发生......
  • @Nemo... 我同意你的看法。但是,在我们的特殊情况下,我们选择检测和解决死锁而不是避免死锁,因为发生死锁的可能性非常小。
  • 对不起@Juggler,但我不认同这种哲学。这是软件。没有所谓的“极其罕见”。只有“从不”和“错误”。或者正如尤达所说,没有尝试。
  • @Nemo...好吧。 :-)。谢谢
  • @Nemo,好吧,如果你正在编写一个数据库事务系统,其中事务的内容由更高级别的代码提供,中止事务并重试可能是合理的死锁(Berkeley DB 会这样做,许多 SQL 实现也是如此)。所以我不会说这绝不是一个合理的方法。这只是很少一种合理的方法——尤其是当你取消有问题的线程时必须有一个回滚计划

标签: c linux condition-variable


【解决方案1】:

您可以使用延迟取消积分。在您的线程中,使用pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldstate);(这是默认设置,但明确表示永远不会有坏处);然后使用pthread_setcancelstate 禁用取消,除非条件变量等待您希望被取消。确保使用pthread_cleanup_push 设置取消清理处理程序;这不能很好地与 RAII 配合使用。

现在您可以 pthread_cancel 您的线程。执行取消清除处理程序,按照注册的相反顺序,调用 TLS 数据析构函数,然后线程退出(不从条件变量等待返回)。

当然,这是一个相当丑陋的设计。理想情况下,您应该完全避免死锁;如果那是不可能的,如果是我,我会安排一个线程一次阻塞单个 cvar,并基于这些 cvar 构建更高级别(显式服务员列表)构造以处理多个服务员,同时仍然允许线程可以单独寻址。

【讨论】:

  • 您能详细说明一下吗?在启用取消和等待条件变量之间没有基本的竞争条件吗?也就是说,您持有一个互斥锁,启用取消,然后尝试等待 cond var... 但与此同时,有人认为您陷入僵局并在您持有互斥锁时对您进行核攻击?
  • @Nemo,来自 pthread_cond_wait 手册页:“条件等待(无论是否定时)是一个取消点。当线程的可取消启用状态设置为 PTHREAD_CANCEL_DEFERRED 时,作用于在条件等待中的取消请求是在调用第一个取消清理处理程序之前(实际上)重新获取互斥锁。”所以你的清理处理程序必须释放互斥锁。
【解决方案2】:

只需编写代码即可完全满足您的需求。由于条件变量不提供这种行为,因此没有捷径可走。所以就写吧。这没什么难的。例如,您可以设置一个特殊标志,唤醒所有在条件变量上阻塞的线程,然后对线程进行编码以检查该标志以查看是否应该重新进入睡眠状态。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-31
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-08
    • 2017-12-21
    相关资源
    最近更新 更多