以非阻塞方式执行一个函数
在 skynet 中,服务之间并行运行,而每个服务自身的业务都是串行的。一个服务由开发者自行切分成多个时间片,每个时间片串行运行在不同的工作线程上。最常见的做法是在每个服务中运行一个 Lua 虚拟机,用 coroutine 切分时间片,这样从编写代码的角度看,任务是连续的。
这个设计的目的是,让开发者轻松享受到多核带来的并发性能优势,同时减轻编写多线程程序带来的心智负担。
用过 skynet 的应该都碰到过:当我们在服务中不小心调用了一个长时间运行而不返回的 C 函数,会独占一个工作线程。同时,这个被阻塞的服务也无法处理新的消息。一旦这种情况发生,看似是无解的。我们通常认为,是设计问题导致了这种情况发生。skynet 的框架在监测到这种情况发生时,会输出 maybe in an endless loop
。
如果是 Lua 函数产生的死循环,可以通过发送 signal 打断正在运行运行的 Lua 虚拟机,但如果是陷入 C 函数中,只能事后追查 bug 了。