IOCP线程池的开发-(1)

在以前的文章中,我已经描述了使用IOCP来编写一个可以支持大量数据连接的网络通信部分的内容。但是IOCP的作用仅限于用来编写网络通信吗?答案是否定的。在《windows核心编程》一书中,作者也说明了使用IO完成端口允许我们向一个设备同时发送多个IO请求,它允许一个线程发出IO请求,另一个线程对结果进行处理,这项技术具有高度的伸缩性和最佳的灵活性windows核心编程第297页)。这就说明了IOCP不只是用来开发网络代码,只要是IO的投递处理都可以用IOCP来处理。这样的话我们就可以使用IOCP来开发我们的线程池了。
 
为什么非要用IOCP来开发线程池呢?让我们来分析一下线程池的作用,以及IOCP来开发线程池的好处。
 
当我们做服务端开发的时候,经常需要对一些慢设备进行操作(例如数据库,文件等等)。当我们只使用一个线程来处理慢设备的时候,会发现我们的程序运行起来CPU利用率过低,处理速度过慢。如果我们使用多线程同时来操作,就可以大大提高效率。但是我们自己写多线程调度的时候却存在2个难以处理的问题:
1 :我们需要开多少个线程合适?因为我们知道过多的线程在CPU调度切换的时候会有相当大的消耗,从而造成效率的低下(一些初学者理解的线程越多速度越快的观点是错误的)。
2 :我们如何调度线程?当我们操作多线程的时候我们如何选取合适的线程来处理呢?如果只用一个指定的线程那自然不行(这样的话和单线程没有任何区别了)。那我们又如何选择合适的线程呢?我想大家一定可以实现,但是实现的结果就是需要进行大量的判断,然后来选择合适的线程处理。这样本身增加了编码复杂度,而且降低了效率。(大道至简,这句话用在开发上简直是太精辟了)。
 
而这两个问题,IOCP却恰恰已经为我们解决了。
1 IOCP在一台机器上开的线程数量是有一定规定的。一般来说是CPU数量的*2 + 2。(有的书上说是*2)。
2 :对于线程的调度,IOCP采用了后进先出的原则。例如当有ABCD 4个等待线程队列,那么当数据投递过来以后IOCP会选择最后一次调用GetQueuedCompletionStatus的线程去处理这个数据。例如最后调用GetQueuedCompletionStatus的线程为A,那么线程A会被唤醒。同理当线程A正在处于繁忙状态时,则剩余的等待线程队列中的最后一个调用GetQueuedCompletionStatus函数的线程会被唤醒,去进行处理。
 
通过以上两点来看,使用IOCP来编写线程池对于开发服务端程序是非常有好处的。
 
那么我们怎样用IOCP来编写线程池呢?
首先我们来分析一下IOCP在网络通信过程中是如何实现的,这有助于我们用IOCP来编写线程池。
 
在网络通信中,当我们使用IOCP来接收数据的时候,我们首先需要投递一个WSARecv函数,用来通知系统我们已经投递了接收请求,当系统接收到数据以后,会自动填充重叠结构,并从函数GetQueuedCompletionStatus返回这个重叠结构和数据的长度。而且我们也可以使用函数
PostQueuedCompletionStatus 来投递我们自己定义的消息。这一点在IOCP编写线程池的时候尤为重要。
 
下一篇将将如何实现IOCP线程池。

你可能感兴趣的:(线程池,Delphi,iocp,休闲,完成端口)