33.1 基本想法:事件循环
在深入细节之前,我们先看一个典型的基于事件的服务器。这种应用都是基于一个简单的结构,称为事件循环(event loop)。
while (1) {
events = getEvents();
for (e in events)
processEvent(e);
}
主循环等待某些事件发生(通过 getEvents()调用),然后依次处理这些发生的事件。处理事件的代码叫作事件处理程序(event handler)。重要的是,处理程序在处理一个事件时,它是系统中发生的唯一活动。因此,调度就是决定接下来处理哪个事件。这种对调度的显式控制,是基于事件方法的一个重要优点。
33.2 重要 API:select()(或 poll())
阻塞(或同步, synchronous)接口在返回给调用者之前完成所有工作。非阻塞(或异步, asynchronous)接口开始一些工作,但立即返回,从而让所有需要完成的工作都在后台完成。
33.4 为何更简单?无须锁
使用单个 CPU 和基于事件的应用程序,并发程序中发现的问题不再存在。具体来说,因为一次只处理一个事件,所以不需要获取或释放锁。基于事件的服务器不能被另一个线程中断,因为它确实是单线程的。因此,线程化程序中常见的并发性错误并没有出现在基本的基于事件的方法中。
33.5 一个问题:阻塞系统调用
当事件循环阻塞时,系统处于闲置状态,因此是潜在的巨大资源浪费。因此,我们在基于事件的系统中必须遵守一条规则:不允许阻塞调用。