Skynet源码阅读笔记(六)-skynet的线程类型
skynet中的线程类型可以分为一下几种类型
- 主线程
- worker 线程
- timer 线程
- monitor 线程
- socket 线程
这些线程的初始化都在start函数里,由主线程驱动
主线程
主线程只负责初始化工作,它主要是在start中创建了一些基础服务、创建出其他线程。执行完初始化后,主线程就会阻塞在最后等待其他结束。
|
|
monitor 线程
monitor线程执行的函数是thread_monitor
|
|
该函数每5秒跑一下检测,判断对应线程的check_version 是否和其version相等,如果相等就说明可能存在死循环,调用 skynet_context_endless 来对ctx的 endless进行赋值。
monitor 这个结构如下
|
|
本质上monitor是维护了一个条件变量 + skynet_monitor数组,每个work线程都拥有一个自己的skynet_monitor。因为worker线程和monitor线程在使用skynet_monitor时,写的是skynet_monitor的不同字段,而读操作即使出现异步问题也不要紧,所以这边可以不需要加锁。
monitor中的sleep 表示由多少个work线程在睡眠,睡眠的worker线程会阻塞在对应条件变量上等待被唤醒。
worker线程
worker 线程执行的是thread_worker 函数
|
|
thread_worker这边主要就是执行 skynet_context_message_dispatch 函数,如果这个函数的返回值是空,则等待下一次的执行
具体看一下 skynet_context_message_dispatch 的内容
|
|
skynet_context_message_dispatch 就是从队列中消费消息,weight在这起到的作用就是每次执行队列总长度的1/(2^weight)
所以前8条线程应该都是执行完所有消息,8-16条每次执行1/2的消息长度的数据,一次类推。
还有一个值得注意的,skynet_monitor_trigger就是会在这往skynet_monitor写入当前的服务ID,以便monitor线程进行监控
执行消息的函数是dispatch_message,dispatch_message的内容也不长,完整的看一下
|
|
dispatch_message 准确来说目的就是执行ctx->cb,但外部根据执行环境决定是否写入日志和统计函数执行时间。
小结
这边先看了一下主线程、monitor线程和worker线程是如何工作的,另外两个线程下一次再分析。
主线程主要是初始化环境以及各个其他线程,然后join等待其他线程结束 monitor线程可以认为就是每5秒判断一次是否当前执行的某个worker线程进入了死循环。 worker线程就是将消息队列中的消息取出,并调用对应服务的cb函数。