代码之家  ›  专栏  ›  技术社区  ›  dimba

如何设计多线程应用程序

  •  5
  • dimba  · 技术社区  · 14 年前

    我有一个多线程应用程序。每个模块在单独的线程中执行。 模块包括:

    - network module - used to receive/send data from network
    - parser module - encode/decode network data to internal presentation
    - 2 application module - perform some application logic on the above data one after other
    - counter module - used to gather statistics from other modules
    - timer module - used to schedule timers
    - and much more ...
    

    一些模块被其他模块使用(例如,所有模块都使用定时器和计数器),对于从网络接收到的每条消息,应该以非常高的速率进行处理。

    这是一个相当复杂的应用程序,设计看起来“合理”。从另一方面来说,我不确定这样的设计,每个模块的线程,是“最好的”一个?尤其是这样的设计恐怕会“鼓励”很多语境的转换。

    有什么好的指导方针或开源项目可以从中学习如何对线程应用程序进行“正确”的设计吗?

    5 回复  |  直到 14 年前
        1
  •  22
  •   Chris Becke    14 年前

    这种设计是低效的,因为很少的任务分解会产生和cpu一样多的任务。

    更合理的设计是将任务分解为“作业”,然后使用线程池机制来分派这些作业。 与每模块线程方法相比的优势:

    • 线程池利用所有内核。如果有模块,则每个模块有一个线程<核心你有闲置的核心。

    • 线程池通过保持活动线程和内核之间的奇偶校验来最小化争用和资源。每个模块有线程,如果模块大于;内核会导致不必要的额外上下文切换,并且(在某些平台上)每个线程会耗尽其他有限的每进程资源(如虚拟内存)。

    • 线程池允许“模块”一次执行多个作业。每个模块的线程数意味着最繁忙的模块仍然只有一个核心。

        2
  •  7
  •   TheUndeadFish    14 年前

    我不会称自己为多线程设计专家。但我至少在处理线程时遇到过各种问题,试图将它们设计为协同工作(通信、锁定资源、等待线程结束等)。

    在这一点上,我的经验法则是,我必须证明每个新线程的存在。例如,如果我使用的网络层同时提供了同步和异步API,我真的可以证明让网络代码在新线程中使用同步调用而不是只在主线程中使用异步调用是合理的吗?在您的例子中,有多少模块因为特定的原因需要自己的线程。有没有可以从主线程依次调用的?

    如果有些线程没有存在的充分理由,那么 可以 只需将该模块放在主线程中,就可以省去一些麻烦和复杂性。

    我不知道有什么“正确”的方法。很多都归结为应用程序实际应该做什么的细节。

        3
  •  3
  •   Starkey    14 年前

    异步事件在单独的线程中也很好。你的定时器模块在这里看起来是个不错的选择。

    您可能希望将其他模块放在一个线程中,以降低应用程序的复杂性。但是,如果你有一个多处理器系统,你可能想把它们分开。

    有一个很好的锁定资源和互斥处理策略来防止死锁。依赖关系图(使用白板!)可能有助于使你的设计正确。

    祝你好运!听起来像是一个复杂的系统,将导致许多小时的有趣的发展!

        4
  •  1
  •   Remus Rusanu    14 年前

    什么站台?

    High Performance Windows Programs .

    还有其他一些因素在起作用,比如网络模块必须处理的协议类型。请求-响应协议通常由每个请求一个线程来处理,它们做得很好,但是高吞吐量的大规模协议在该模型中的表现并不好,特别是因为需求。

    归根结底,仅仅从这个简短的描述很难判断你的设计是否合理。就我个人而言,我倾向于IO完成驱动的线程模型,而不是逻辑模块驱动的线程模型,但那只是我自己。

        5
  •  1
  •   asr    14 年前

    • 网络模块

    认可的。

    • 解析器模块 + 2应用模块

    你确定这三个线程不能合并成一个主数据处理线程吗?如果是这样的话,那么就可以像其他人建议的那样使用线程池,让N个线程执行这个处理。

    • 定时器模块

    这在大多数平台上可能是合理的,因为您需要一个消息处理循环来调度计时器事件。另外,如果您需要一个GUI,它可能就是您想要的地方。

    我建议在每个线程中保留单独的计数器,并在需要时为它们轮询(消息队列)。

    • 还有更多。。。