【问题标题】:Sleeping a worker thread in a file server在文件服务器中休眠工作线程
【发布时间】:2011-09-11 02:58:41
【问题描述】:

我正在实现一个文件服务器,它接收来自多个客户端的请求。每个客户端发送多个请求。在服务器端,每次有新客户端连接时,主线程都会产生一个新的工作线程来处理请求。一个工作线程处理来自为其创建它的客户端的所有请求。因此,线程处理完一个请求后,等待来自同一个客户端的另一个请求到达时被主线程唤醒。

我不确定如何实现最后一行。这就是我如何让线程休眠并再次唤醒它。

谢谢

【问题讨论】:

    标签: c linux multithreading sockets


    【解决方案1】:

    我通过在客户端连接开始时创建的线程解决了这个问题,然后线程直接接收并向客户端发送消息,而不是在工作线程完成任务后主线程接收和发送消息。

    【讨论】:

      【解决方案2】:

      你应该研究生产者-消费者的问题。简而言之,您想做这样的事情:

      • 工作线程尝试从队列中获取“作业”
      • 如果队列为空,线程阻塞(信号量/条件变量),否则获取作业并处理它
      • 主队列作业放入队列并通知工人(“嘿,有工作要做”)
      • 收到通知的工作人员立即醒来并尝试从队列中获取一份工作

      诀窍是做到真正优雅:

      • get 应该会自动 当队列为空时阻塞
      • put 应该会自动 信号等待它的工作人员

      您将如何利用 Linux 为您提供的功能来做到这一点?

      现在,回到你的问题。为每个客户端启动一个线程似乎有点可疑。如果您可以有一个线程池来处理来自任何客户端的请求,那将会方式更简单。

      【讨论】:

      • 为每个客户端启动一个线程绝对是更简单。它可能效率较低,但在现代实现中,我怀疑差异是否像您想象的那么大。
      • @R.. 你可能是对的。尽管如此,我发现每秒多次启动线程并让它们死掉是令人不安的。同样,对于现代的东西(clone 等),为每个客户端启动线程可能是非常可行的。
      • 我的随意测试显示pthread_create 的成本与打开/dev/null 2-4 次的成本大致相同。当然,这并不一定要考虑任何可能的缓存/TLB 影响,但如果您的应用程序很大程度上受 IO 限制和/或系统调用限制,那么这不太重要。
      【解决方案3】:

      您的客户端处理线程是否为客户端保存任何状态?如果是这样,我可以理解为什么您需要为每个客户端提供一个专用线程。如果是这种情况,您可以按照 Cnicutar 和其他海报的建议为每个客户端处理程序线程使用生产者-消费者队列。我通常将信号量与互斥锁一起使用,因为这种同步在所有平台上都可用,但 condvars 可以。目前尚不清楚当文件请求进入时如何识别客户端,因此管理客户端线程可能会很尴尬,也可能不会。当一个文件请求进入主线程时,如何知道将它推送到哪个队列?

      Rgds, 马丁

      【讨论】:

        【解决方案4】:

        你有几种可能,但我实现了一个类似的多线程解决方案,如下所示:

        • 允许您的工作线程的方法在无工作时返回
        • 当你的父线程收到请求时,将其添加到工作线程的队列中,并调用“Wakeup”方法,如下所示:

          private void Wakeup()
          {
              if (!_workerThread.IsBusy)
                  _workerThread.RunWorkerAsync();
          }
          

        这将使您的线程不会在睡眠状态下挂起,在这种状态下它需要定期检查是否已请求唤醒。这将唤醒工作线程的责任放到了父线程上。

        【讨论】:

        • 线程在睡眠状态下不会“挂起”。当它们处于睡眠状态时,它们不会“定期检查是否已请求唤醒”。休眠线程消耗的 CPU 正好为零。
        【解决方案5】:

        您不会“让线程进入睡眠状态”。线程在进行任何阻塞系统调用时都会休眠。

        有很多方法可以实现您所描述的内容,最常见的可能是"Thread pool pattern"。这通常使用线程安全队列来实现,而后者又可以使用互斥锁和条件变量来实现。

        工作线程在等待条件变量(pthread_cond_wait)时会进入睡眠状态,主线程会通过发出条件变量(pthread_cond_signal)的信号将其唤醒。

        稍作搜索就会找到一些基于 pthread 的队列示例代码。

        【讨论】:

          【解决方案6】:
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-12
          • 1970-01-01
          相关资源
          最近更新 更多