有太多线程吗?

mur*_*mur 2 c c++ multithreading g++

环境:Ubuntu 16.04 - Linux,使用GCC编译C++ 11.软件不需要跨平台 - 但在其任务中是高效的,并且是一个优秀的守护进程.

我目前有一个简单的应用程序,它基本上充当第三方服务和websocket连接之间的中介.所以用户通过websocket连接我的服务与所述第三方服务交谈.

| End-User |  <-C1-> | My Application | <-C2-> | 3rd Party Service |
Run Code Online (Sandbox Code Playgroud)

我的应用程序目前有2个主线程:

  1. 线程1 - 收听websocket连接,每当收到消息时,它会将包含消息的对象和请求所述消息的websocket连接推送到fifo任务队列.

  2. 线程2 - 循环显示消息队列,并弹出消息并对其进行处理

问题是线程1非常快,并且可以轻松处理100个websocket连接.线程2有时阻塞任务并且可能很慢,因为所述第三方服务的某些队列项处理需要一段时间.这意味着,如果用户A确实请求1(需要5秒钟响应),而后来用户B发出请求2,则必须等待用户A的请求1完成,即使请求2花费不到1毫秒.

我建议的解决方案是:

  • 线程1 - WebSocket连接侦听器
  • 线程2任务委托人
  • 线程3 - 100 - 任务工作者

线程1可以轻松处理100个websocket连接,并且每个连接可以请求任务可能需要1ms到1分钟.所有线程3 - 100都在睡觉.这么多线程的原因是因为如果有50-60个连接都会产生不同的长时间运行请求,那么这些耗时调用中的每一个只会阻塞一个线程,其他线程仍然可以自由地在队列上工作,并且做其他任务.

我知道切换线程是一个密集型操作,但我不知道除了mulithreading之外的任何其他方法.

我用单个线程解决了同样的问题 - 但问题是服务器在等待第三方服务时阻止处理任何websocket消息.所以我把它碰到了两个线程 - 一个用于websocket,另一个用于处理任务队列.但现在问题是任务队列上的单个工作人员很慢,因为它正在顺序处理阻塞IO操作.

这听起来像是一个糟糕的设计理念吗?对最佳实践的任何想法?

Ric*_*ges 6

有太多线程吗?

100个主题

如果在任何桌面/服务器上有点不理想,应该没问题.我有一台笔记本电脑拒绝在一个过程中约2000个线程后继续.

其他策略

对于最大吞吐量,常见的设计决策是每个CPU核心约1个线程,并采用基于异步电路的设计.

一些例子:

  • libuv

  • 提高:: ASIO

  • libdispatch

  • win32异步操作

  • 每个核心 1 个线程适合 CPU 瓶颈任务;但当问题是 IO 限制时,它就变得更加模糊。我曾开发过一个具有 100 个线程的应用程序,这些线程仅执行 ping 任务;因为线程通常处于阻塞函数中等待网络数据。 (2认同)

Jes*_*uhl 5

“是否存在线程过多之类的情况?” - 是的。线程会消耗您可能用完的系统资源。线程需要调度;需要内核的工作以及 CPU 上的时间(即使它们随后决定不执行任何操作)。更多线程会增加复杂性,使您的程序更难以推理和调试。

确实存在线程过多的情况——永远不要创建超出您需要的线程/对您的程序有意义的线程。