skynet的线程安全

skynet是线程安全的

理解这个先要知道skynet 的队列模型

云风blog: skynet设计综述 https://blog.codingnow.com/2012/09/the_design_of_skynet.htmlarrow-up-right

skynet 的消息调度

Skynet 维护了两级消息队列。

每个服务实体有一个私有的消息队列,队列中是一个个发送给它的消息。消息由四部分构成:

struct skynet_message {
    uint32_t source;
    int session;
    void * data;
    size_t sz;
};

向一个服务发送一个消息,就是把这样一个消息体压入这个服务的私有消息队列中。这个结构的值复制进消息队列的,但消息内容本身不做复制。

Skynet 维护了一个全局消息队列,里面放的是诸个不为空的次级消息队列。

在 Skynet 启动时,建立了若干工作线程(数量可配置),它们不断的从主消息列队中取出一个次级消息队列来,再从次级队列中取去一条消息,调用对应的服务的 callback 函数进行出来。为了调用公平,一次仅处理一条消息,而不是耗净所有消息(虽然那样的局部效率更高,因为减少了查询服务实体的次数,以及主消息队列进出的次数),这样可以保证没有服务会被饿死。

用户定义的 callback 函数不必保证线程安全,因为在 callback 函数被调用的过程中,其它工作线程没有可能获得这个 callback 函数所熟服务的次级消息队列,也就不可能被并发了。一旦一个服务的消息队列暂时为空,它的消息队列就不再被放回全局消息队列了。这样使大部分不工作的服务不会空转 CPU 。

一个服务有一个接收消息队列,这个消息队列如果有消息,就挂到了全局消息队列

线程从全局消息队列中取一个消息队列,处理一个消息,这个服务的消息队列已经被取出来了,也就不会被其他线程占用。

所以一个服务的执行是线程安全的,不用担心并发问题

最后更新于