skynet是一个异步响应的单进程多协程系统。
在skynet的服务中,如果调用了一个阻塞API(skynet.call skynet.sleep),这个服务将会被挂起。在阻塞返回之前,这个服务仍然 可以响应其他消息。这个就会造成时序问题了。
以下为例
local CMD = {}
function CMD.func1()
print('------func1 1')
print('------func1 2')
end
function CMD.func2()
print('------func2 1')
skynet.sleep(2000)
print('------func2 2')
end
以上的代码中,若func2先调用,然后进入了sleep中,此时func1也会响应调用。
所以最后看到的输出有可能是这个样子的
------func2 1
------func1 1
------func1 2
------func2 2
还有可能是
func2 1 func2 1
func2 2 func2 2
为了避免第2 种情况的发生,需要对它进行加锁
local queue = require "skynet.queue"
local cs = queue()
function CMD.func2()
cs(function()
print('------func2 1')
skynet.sleep(2000)
print('------func2 2')
end)
end
这样加锁以后,无论如何也不会出现第2种情况,它的输出只会是
func2 1 func2 2
func2 1 func2 2
func2 1 func2 2
虽然skynet是个单线程的系统,但是它是异步响应的,所以对于时序问题也要加倍小心。
原文链接在这里
https://github.com/cloudwu/skynet/wiki/CriticalSection
https://www.processon.com/i/568c6ea4e4b0e51d149a085f
这个网站解决了大家开始设计阶段的问题,轻量级的各种设计模型,强烈推荐。