当前位置: 技术问答>linux和unix
是选择多线程还是I/O复用呢?
来源: 互联网 发布时间:2017-03-05
本文导语: 在Linux下编写多用户和服务器连接传递数据的程序,在服务器端是使用多线程编程呢,还是用I/O复用呢?最后这个程序还要移植到arm开发板上。请问哪种方案比较好?谢谢! | 这个主要受程序...
在Linux下编写多用户和服务器连接传递数据的程序,在服务器端是使用多线程编程呢,还是用I/O复用呢?最后这个程序还要移植到arm开发板上。请问哪种方案比较好?谢谢!
|
这个主要受程序需求影响,如果业务逻辑是阻塞的,你觉得I/O复用还能用吗? 很明显用不上了。
如果条件允许使用I/O复用,那么当然I/O复用比多线程效率要高N倍了。
最后,多线程和I/O复用只是两种系统接口,不是互斥关系,你可以同时使用,而且这种情况是很普遍的。
比如:
一个服务端接受客户端上报的日志,并存入数据库,还会接受客户端的日志查询,将数据库查询结果返回。
要是你,你怎么思考这个架构?
1,Mysql查询接口都是阻塞接口,肯定不能和网络I/O同线程。
2,基于1的考虑,Mysql查询逻辑挪到线程里并发的做,一个线程同一时刻执行一个阻塞的Mysql查询。
3,网络I/O线程采用I/O复用,对于每一个请求,将其派发到Mysql线程池进行处理,Mysql线程池将查询数据等结果集返回到网络I/O线程。
楼主可能对2,3步的编码细节有疑惑,简单给你说两句,你自己思考一下:
任务派发:Mysql线程池epoll监听pipe,网络I/O线程得到某client请求后遍历线程池,找一个排队任务最少的线程,将任务push给该线程的队列,向该线程pipe写1字节作为事件通知,该client进入等待结果集状态(在收到结果集前不会Push第二个Mysql请求)。
任务完成:Mysql线程完成一个client的一个Mysql请求,需要将结果集push回网络I/O线程。道理一样,网络I/O线程epoll pipe,Mysql线程push结果集到队列,向pipe写1字节通知I/O线程,于是I/O线程取出结果集,找到对应的client,修改client状态为完成查询并将结果集写给client。
此后,继续从client读请求,push给线程池,线程池push回I/O,就这么一个过程。
编码细节就是粘包问题以及状态机,包括正确的使用epoll非阻塞编程这些基础功。
如果条件允许使用I/O复用,那么当然I/O复用比多线程效率要高N倍了。
最后,多线程和I/O复用只是两种系统接口,不是互斥关系,你可以同时使用,而且这种情况是很普遍的。
比如:
一个服务端接受客户端上报的日志,并存入数据库,还会接受客户端的日志查询,将数据库查询结果返回。
要是你,你怎么思考这个架构?
1,Mysql查询接口都是阻塞接口,肯定不能和网络I/O同线程。
2,基于1的考虑,Mysql查询逻辑挪到线程里并发的做,一个线程同一时刻执行一个阻塞的Mysql查询。
3,网络I/O线程采用I/O复用,对于每一个请求,将其派发到Mysql线程池进行处理,Mysql线程池将查询数据等结果集返回到网络I/O线程。
楼主可能对2,3步的编码细节有疑惑,简单给你说两句,你自己思考一下:
任务派发:Mysql线程池epoll监听pipe,网络I/O线程得到某client请求后遍历线程池,找一个排队任务最少的线程,将任务push给该线程的队列,向该线程pipe写1字节作为事件通知,该client进入等待结果集状态(在收到结果集前不会Push第二个Mysql请求)。
任务完成:Mysql线程完成一个client的一个Mysql请求,需要将结果集push回网络I/O线程。道理一样,网络I/O线程epoll pipe,Mysql线程push结果集到队列,向pipe写1字节通知I/O线程,于是I/O线程取出结果集,找到对应的client,修改client状态为完成查询并将结果集写给client。
此后,继续从client读请求,push给线程池,线程池push回I/O,就这么一个过程。
编码细节就是粘包问题以及状态机,包括正确的使用epoll非阻塞编程这些基础功。
|
如果I/O复用能够达到足够的性能,就没必要上多线程,这个决定权在你自己以及产品的需求
|
个人感觉用I/O复用吧,多线程用的不好就可能有导致整个程序崩溃的风险。