skynet踩坑记录(三)skynet.call的挂起实际中可能造成的后果。

       在刚开始使用skynet的时候,就已经知道call方法会挂起。但是一直到今天,都无法深刻理解这个挂起的意思。直到碰到了这个问题。解决后做此记录。

       1.先描述一下出现的情况。

        skynet踩坑记录(三)skynet.call的挂起实际中可能造成的后果。_第1张图片

       先暂且不管为什么要对db进行这么多次操作(原因太多)。在这个需求下,我本是想执行顺序为 1234,但是实际上确时1324。这会导致3拿到的是2更新之前的数据。今日参加次数就会在执行4的时候,没有能更新到2更新的内容。

       2.为什么会出现这样的情况呢。

       首先要了解 lua协程。在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只有在明确的被要求挂起的时候才会被挂起。一般使用协程的时候,因为cpu的性能问题,会让我们感觉和多线程差不多。但是重点就是,同一时刻,只有一个协程在运行,而且在他让出cpu的时候,cpu才回去处理别的协程。

       在上面的情况下,就是因为在步骤1的时候,调用了skynet.call。这个东西会挂起协程,也就是让出cpu。然后cpu就是处理了下面的协程,所以先调用了3。

       3.怎么处理

       有两个方法:a.修改业务,将这两个增加写到一起。

                            b.使用消息队列,skynet.queue。(代码很简单,就几行,即处理完当前协程的方法再调用下一个协程的方法)(云风前辈在blog也写过,skynet.queue,就是用来处理这了多协程,又要保证次序的问题。)

       4.处理的注意事项,使用skynet.queue的时候,一定要确保丢进队列的顺序是1234,我自己就因为没有能很好的理解call的挂起,让上面两个协程分别把方法丢到队列里(再次踩坑,加深理解),最后丢进去的顺序又是1324。。。。查了好久,才找到。再次提醒,skynet.call会挂起协程。其实再很多游戏业务中,也会有这种场景,需要多注意。(如果是关于重要数据的修改,麻烦就大了,例如金币变动等)

       5.虽然从技术上也解决了,但是最后我是修改了逻辑,将两个方法写成一个。没必要进行四次DB操作。但是这次的确也加深了我对协程挂起的理解。

你可能感兴趣的:(skynet,后端)