当我们想要设计一个通用的事件处理(I/O Demultiplexing)或反应器模式模型时。我们使用的底层系统调用是“select”或“poll”。但是这两个系统调用在常见的 FD 集上都不是线程安全的。不能在多线程环境中使用。
处理跨多个 I/O 的多线程事件的更好方法是什么。
我可以看到的一种方法是,主线程recv 的任何事件并推送到线程池的共享队列中。但是工作线程不能通过 I/O 发送数据导致同步问题。也有内存溢出的缺点。
欢迎所有可能的建议。提前致谢。
当我们想要设计一个通用的事件处理(I/O Demultiplexing)或反应器模式模型时。我们使用的底层系统调用是“select”或“poll”。但是这两个系统调用在常见的 FD 集上都不是线程安全的。不能在多线程环境中使用。
处理跨多个 I/O 的多线程事件的更好方法是什么。
我可以看到的一种方法是,主线程recv 的任何事件并推送到线程池的共享队列中。但是工作线程不能通过 I/O 发送数据导致同步问题。也有内存溢出的缺点。
欢迎所有可能的建议。提前致谢。
大多数 Unix 提供了更多可扩展的选择/轮询替代方案,可用于多线程环境:
但是在多线程环境中正确处理可能会很棘手,因此您可能需要查看现有的抽象层,例如boost.asio
另一方面,boost.asio 确实引入了一些不可忽略的开销——我在http://nginetd.cmeerw.org收集了一些关于此的信息和 epoll/kqueue 的替代抽象
一种方法是拥有一个输入线程、一个输出线程、多个工作线程和两个阻塞队列。
输入线程解析输入消息并将它们放入队列 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”程序的不同方法以及每种方法的优缺点。
查看“生产者 - 消费者问题”,这是线程安全问题的一个很好的起点。它还可以扩展到多个生产者和多个消费者。