【问题标题】:C++ - threads and multiple queuesC++ - 线程和多个队列
【发布时间】:2010-10-28 06:51:41
【问题描述】:

我需要构建一个由工作人员(表示为线程)和(多个)队列组成的系统。单个作业在其中一个队列中等待并等待工作线程处理它们。每个工作人员只能处理来自某些队列的作业。没有旋转等待。 C/C++、pthreads、标准 POSIX。

对我来说,问题是“多队列”的事​​情。我知道如何用一个队列来实现它。工作人员需要等待他们可以处理的所有队列(等待其中的任何一个)。

在 Windows 上我会使用 WaitForMultipleObjects,但这需要是多平台的。

我不想要任何特定的代码,只想要我应该使用的模型的提示或描述。提前致谢。

【问题讨论】:

    标签: c++ multithreading queue posix pthreads


    【解决方案1】:

    我最近一直在考虑这个问题,我能想到的唯一想法是(假设您有线程安全队列)只有多个线程服务于一个队列。

    然后,您可以让一个或多个工作线程将作业添加到单个队列中,并让一个或多个工作线程阻塞队列,直到它们找到要处理的内容。

    如果您曾经有多个队列需要多个工作线程轮询,那么解决方案可能是为每个队列添加一个额外的线程和一个额外的队列。额外的线程每个都阻塞在自己的单个队列中,但只是将作业转发到额外的队列。现在现有的工作线程又回到了阻塞在单个队列上。

    【讨论】:

      【解决方案2】:

      怎么样:

      • 所有工作线程都在一个信号量上等待
      • 当任何东西添加到队列中时,信号量会增加,从而唤醒单个线程
      • 线程检查它感兴趣的队列,处理其中一个,然后返回等待信号量

      您将需要额外的互斥锁来控制对队列的实际读写。

      【讨论】:

        【解决方案3】:

        听起来您应该使用boost::threadboost::conditionstd::queue

        【讨论】:

          【解决方案4】:

          您可以这样做:每个作业都有一个与之关联的“队列”。例如:

          假设您有 2 个队列。你的工作可以说:

          job[0].queue = 1; /* That job is in queue 1 */
          job[1].queue = 1;
          job[2].queue = 2; /* this job is in queue 2 */
          ... 
          etc
          

          那么你就有了你的“线袋”。一个线程简单地选择一个工作——比如说,工作[2]。如果只允许该线程处理来自队列 1 的作业,那么它将将该作业放回就绪队列并选择不同的作业。

          所以每个线程都知道它可以处理哪些队列,并且当它选择一个作业时,它会确保该作业的“队列”字段匹配。如果没有,它会选择不同的工作。

          (这在很多方面是进程调度在 linux 中的多核上的工作方式。每个进程都有一个位掩码,说明它允许在哪些处理器上运行,然后处理器确保它之前被“允许”运行该进程这样做。)

          【讨论】:

            【解决方案5】:

            与其为每个队列设置一个单独的锁,不如为所有队列设置一个锁?

            1. 等待锁定
            2. 获取锁
            3. 从任何队列中出队
            4. 解除锁定
            5. 处理出队的项目
            6. 转到第 1 步

            假设出队花费的时间可以忽略不计(因此锁只持有可以忽略不计的时间),可能不需要多个锁。

            【讨论】:

            • 我认为这行不通。工作人员仅处理来自特定队列的作业。如果“坏”队列中只有一个作业,则该工作人员将忙于等待,直到其他工作人员接受该工作。
            【解决方案6】:

            我要做的是使用 boost::asio 来排队数据,这样你的多个线程就可以尝试了。您可以通过 post 命令将 ref 传递给队列,并相应地让线程处理。

            【讨论】:

              【解决方案7】:

              您可以使用condition variable。让您的工作线程等待条件变量。当作业被添加到任何作业队列时,向条件变量发出信号。然后,当工作线程唤醒时,它会检查它正在等待的队列。如果他们中的任何一个有工作,它就会将该工作从队列中删除。否则,它会返回等待条件变量。等待条件变量会使线程进入睡眠状态,因此不会消耗 CPU 时间。

              当然,不用说您应该使用互斥锁(例如pthread_mutex_t)保护对作业队列的所有访问。

              【讨论】:

              • 好主意,但这会在将作业添加到空队列时唤醒所有工作线程。我想无论如何我都会这样做,但是有没有办法只唤醒“正确”的线程(理想情况下只有一个正确的线程)?
              • pthread_cond_signal() 将唤醒“至少一个”等待条件变量的线程,而 pthread_cond_broadcast() 将唤醒所有线程。理论上 pthread_cond_signal() 应该大部分时间只唤醒一个线程,但我不知道在实践中是否正确。
              • 但在您的解决方案中,我需要唤醒所有线程,因为作业可能在队列中,而 one 工作人员没有过程。
              【解决方案8】:

              如果每个队列没有太多的工作人员,您可以为每个工作人员创建一个条件变量。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2010-10-22
                • 2011-03-13
                • 1970-01-01
                • 2018-03-09
                • 2013-06-18
                • 2013-07-20
                • 2010-10-29
                相关资源
                最近更新 更多