【问题标题】:Multi-Threaded Event Handling in C++C++ 中的多线程事件处理
【发布时间】:2012-08-22 09:26:43
【问题描述】:

当我们想要设计一个通用的事件处理(I/O 解复用)或反应器模式模型时。我们使用的底层系统调用是“select”或“poll”。但是这两个系统调用在常见的 FD 集上都不是线程安全的。不能在多线程环境中使用。

处理跨多个 I/O 的多线程事件的更好方法是什么。

我能看到的一种方式是,主线程接收任何事件并推送到线程池的共享队列中。但是工作线程不能通过 I/O 发送数据会导致同步问题。还有内存溢出的缺点。

欢迎所有可能的建议。提前致谢。

【问题讨论】:

  • 我会研究 boost asio,它为你包装了底层细节,你可以使用一个更好的界面,它已经可以处理各种 io“事件”,并允许你“发布”自己的事件到要处理的“队列”...
  • 您将使用一个线程进行轮询,并将实际 I/O 分配给工作线程(线程池之外)。

标签: c++ multithreading event-handling signals


【解决方案1】:

大多数 Unix 提供了可在多线程环境中使用的更可扩展的选择/轮询替代方案:

但在多线程环境中正确处理可能会很棘手,因此您可能需要查看现有的抽象层,例如 boost.asio

另一方面,boost.asio 确实引入了一些不可忽略的开销 - 我在http://nginetd.cmeerw.org收集了一些关于此的信息和 epoll/kqueue 的替代抽象

【讨论】:

  • 谢谢.. 我会仔细阅读这些参考资料。
【解决方案2】:

查看"Producer - Consumer problem",这是线程安全问题的一个很好的起点。它还可以扩展到多个生产者和多个消费者。

【讨论】:

    【解决方案3】:

    一种方法是拥有一个输入线程、一个输出线程、多个工作线程和两个阻塞队列。

    输入线程解析输入消息并将它们放入队列 1。工作线程都在队列 1 上等待,处理一条消息并将它们的任何输出放入队列 2。输出线程在队列 2 上等待并将其输出序列化。

    InputThread:
        Loop:
            M = ReadNextMessage
            Q1.push(M)
    
    AddOutput(O):
        Q2.push(O)
    
    WorkerThread:
        Loop:
            M = Q1.pop
            ProcessMessage(M) using AddOutput as needed
    
    OutputThread:
        Loop:
            O = Q2.pop
            WriteOutput(O)
    

    但是我不知道你的意思是 select 不是线程安全的?所有系统调用在技术上都是线程安全的

    这是一个很古老但仍然很有趣的文章,由一个叫 Kegel 的人写的名为“CY10K 问题”的文章。

    http://www.kegel.com/c10k.html

    它讨论了在 Linux 上构建“多 io”程序的不同方法以及每种方法的优缺点。

    【讨论】:

    • select 在同一个 fd 下不是线程安全的。你应该读过手册。
    • @J-16SDiZ 你能解释一下吗?您的意思是如果 fd_set 在线程之外,然后多个线程使用该 fd_set 调用 select?
    • @J-16SDiZ:不正确。 select 是线程安全的,如 POSIX 手册中所述:stackoverflow.com/questions/12084704/…
    • @AndrewTomazos-Fathomling,它并没有回到 UNIX98 中。许多 unix(例如 AIX)明确表示这不起作用。
    猜你喜欢
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多