【问题标题】:Threading issue (chase your own tail)线程问题(追逐自己的尾巴)
【发布时间】:2008-12-08 13:25:38
【问题描述】:

ConnectionManager 等待传入连接。对于每个传入连接,它都会创建一个Connection 实例,用于处理此连接上的入站和出站流量。每个Connection 都有一个Watchdog,它处理“坏连接”情况并调用注册的“侦听器”。一个“侦听器”是ConnectionManager,它关闭连接并删除Connection 实例,这反过来又删除了相应的Watchdog。

等等。一分钟。

Watchdog调用ConnectionManager删除Connection删除Watchdog?看门狗追逐自己的尾巴。

我完全被屏蔽了。我该如何解决这个问题?


解决方案:我将让 Listener 变成异步的,尽管我还不知道如何做到这一点而不会带来太多痛苦。 Watchdog 不知道 ConnectionManager。这是相当通用的。此外,Win32-Thread-API 没有“加入”之类的东西,所以我可能需要使用 GetExitCodeThread()STILL_ACTIVE...

谢谢各位。

【问题讨论】:

  • 我对这个问题感到困惑——如果您每个连接有 1 个看门狗并且触发了该看门狗,您希望删除连接(及其关联的看门狗),不是吗?

标签: c++ multithreading


【解决方案1】:

消息传递。

不要让 Watchdog 调用 ConnectionManager 的方法,而是将消息发布到连接管理器中的队列。这个队列需要是线程安全的。当ConnectionManager在其线程中处理队列时,等待Connection线程结束是安全的。

Watchdog          Queue               ConnectionManager
   |                |                        |
Kill Connection---->|                        |
   |                |<-------------------Get Message
  ---               |                        |
                    |-------------------->Process Message
                    |                        |
                    |                     Kill Connection

【讨论】:

    【解决方案2】:

    如果看门狗在不同的线程中运行,那么问题还算不错 - 看门狗通过异步消息通知 ConnectionManager 删除,然后退出它自己的线程。

    同时,ConnectionManager 线程收到删除消息,并开始删除看门狗。

    为了避免竞争条件,看门狗析构函数应该加入看门狗线程,并清理线程。 (可能还会向看门狗线程发出信号,或 assert() 有关看门狗线程准备退出的信息)。

    【讨论】:

      【解决方案3】:

      如果这些对象中的每一个都在自己的线程中运行,则没有问题。

      Watchdog 通知 ConnectionManager 并返回。
      此时看门狗线程就可以退出了。

      当 ConnectionManager 注意到看门狗事件时,它会终止 Connection 线程。

      【讨论】:

        【解决方案4】:

        如果你小心一点,就没有问题。

        1. ConnectionInstance::a_method() 调用 Watchdog::a_method() 调用 ConnectionManager::a_method

        2. ConnectionManager::a_method() 删除 ConnectionInstance 删除 Watchdog

        3. ConnectionManager::a_method() 返回到 Watchdog::a_method() 返回到 ConnectionInstance::a_method()。只要返回路径不访问任何成员,它就只是从函数返回。按照标准,代码仍然存在,因此您可以安全返回。

        这需要仔细编码和维护,但它看起来并不肮脏。

        异步协议需要同样多的思考。这不仅仅是您需要避免在 ConnectionManager::queue 中请求删除的 Watchdog 和同时对队列执行某些操作的 ConnectionManager 之间的竞争。问题更深:有一段时间 ConnectionInstance 不起作用 - 它已请求删除 - 但仍未删除。它在做什么?一个代码不能静止不动。如果对未失效的 ConnectionInstance 有安全的出路,您也可以自己回滚堆栈,而无需创建额外的异步协议。

        如果它们在同一个线程中,则引发异常的看门狗可能是处理 ConnectionInstance 的一种更简单的方法。

        【讨论】:

          猜你喜欢
          • 2014-03-26
          • 1970-01-01
          • 1970-01-01
          • 2019-10-06
          • 2013-08-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多