浅谈chuck-lua中的多线程
chuck-lua采用actor模式实现多线程,每个线程运行独立Lua虚拟机。通过cthread.new创建线程,cthread.sendmail同步发送消息,邮箱满时发送方阻塞。消息自动序列化反序列化,禁止传递userdata。线程需注册process_mail处理消息,线程创建采用join模式。
chuck-lua 的多线程设计,走的是典型的 actor 模式。你可以通过 cthread.new 创建一个新线程,然后用 cthread.sendmail 把消息扔过去。跟 skynet 那种自带任务调度框架不太一样,chuck-lua 不负责帮你安排线程间的任务流转——每个线程自己维护一个简单的邮箱,其他线程发来的消息先缓存到里面,等着被处理。

光说概念有点干,来看个实际例子,更容易理解。
mtserver.lua
local chuck = require("chuck")
local engine = require("distri.engine")
local socket_helper = chuck.socket_helper
local Distri = require("distri.distri")
local cthread = chuck.cthread
local worker
function on_new_client(fd)
cthread.sendmail(worker,{fd})
end
local fd = socket_helper.socket(socket_helper.AF_INET,
socket_helper.SOCK_STREAM,
socket_helper.IPPROTO_TCP)
socket_helper.addr_reuse(fd,1)
local ip = "127.0.0.1"
local port = 8010
if 0 == socket_helper.listen(fd,ip,port) then
print("server start",ip,port)
local server = chuck.acceptor(fd)
server:Add2Engine(engine,on_new_client)
Distri.Signal(chuck.signal.SIGINT,Distri.Stop)
worker = cthread.new("distri/test/worker.lua")
Distri.Run()
end
worker.lua
local chuck = require("chuck")
local socket = require("distri.socket")
local engine = require("distri.engine")
local clone = chuck.packet.clone
local cthread = chuck.cthread
local Distri = require("distri.distri")
--设置邮件处理函数
cthread.process_mail(engine,function (sender,mail)
local fd = table.unpack(mail)
local s = socket.stream.New(fd)
if s:Ok(4096,socket.stream.decoder.rawpacket(),function (_,msg,errno)
if msg then
s:Send(clone(msg))
else
s:Close(errno)
s = nil
end
end) then
s:SetRecvTimeout(5000)
else
s:Close()
end
end)
Distri.Run()
上面这段代码的逻辑很清楚:主线程启动监听,创建一个 worker 线程,每当有新的客户端连进来,就把 fd 通过 cthread.sendmail 扔给 worker 去处理。
这里需要简单聊一下 chuck-lua 在线程方面的一些设计细节。
因为每个线程都跑在独立的 Lua 虚拟机里,所以你不能直接通过消息把某个虚拟机里的对象传到另一个线程。目前 sendmail 会把作为消息传递的 Lua table 序列化成一种可传输的中间对象,目标线程收到后再重新反序列化成本地 VM 里的 table。好消息是,基本类型(number、string、table 等)都支持,但为了安全,userdata 类型是不允许直接传递的——这一点需要特别留意。
另外,cthread.sendmail 是同步发送的。如果目标邮箱满了(达到了缓冲上限),发送方会被阻塞住。所以,所有期望接收邮件消息的线程都必须调用 cthread.process_mail 来注册消息回调函数。要是不注册,后果就是发送线程永远卡在那里,谁也跑不动。
线程的创建采用 join 模式。也就是说,创建者可以通过 cthread.join 等待目标线程结束。这个设计和常见的线程同步方式一致,用起来比较直观。
Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。
极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。
















