当前位置: 首页 > article >正文

【Lua坑】Lua协程coroutine无法正常完整执行问题

问题:发现Lua协程执行到一半,突然被掐断了一样等到了设定的时间没有正常执行协程后续代码!非必现bug,若发生大概率在高频率使用协程时易触发。

LuaFramework或xLua uLua都自带有协程coroutine,而且基本都使用对象池缓存协程对象,当我们稍微不小心就会引起对象池的问题,也就是持有一个已入池的对象。

1、所有持有写法必须要在使用完协程时手动置空持有对象。

self.co = coroutine.start(function()
        coroutine.waitxxx
        self.co = nil
        ... ...
end)

2、究极神坑!究极神坑!究极神坑!重要的事情说三遍!
当你想持有协程对象时,一定要保证协程执行过至少1次延迟(无论是延迟1帧还是多少秒)例如下面出问题的代码:

local cnt = param --外部传入param参数
local co
co = coroutine.start(function()
        for i = 1, cnt do
                coroutine.waitxxx
                ... ...
        end
​​​​​​​        ... ...
        table.removebyvalue(coTable, co)
end)
table.insert(coTable, co)

不要在意细节,param一定是整数,但可能为0,问题就出在cnt被赋予了一个0,导致for循环没有执行过1次,从而导致协程没有进行过1次延迟waitxxx,所以协程函数体会立即执行完成,关键点是table.removebyvalue(coTable, co)先于table.insert(coTable, co)执行,而table.insert(coTable, co)后执行就加入了1个已回收入对象池的对象。(持有已入池对象行为)后面发生什么就是你会发现有些协程好像无法正常执行完成,明明上一个还在正常输出,下一个就突然消失了,也就是存在这种持有已入池对象行为,要把这种行为全部抹除才能恢复正常,或者直接干脆不用对象池了,可能性能开销会上升点,不然就得排查全部相关的持有代码,将上面代码加一行延迟1帧或延迟渲染结束就能解决问题(保证至少执行过1次延迟!)

local cnt = param --外部传入param参数
local co
co = coroutine.start(function()
        coroutine.waitforendofframe()--延迟渲染结束帧
        for i = 1, cnt do
                coroutine.waitxxx
                ... ...
        end
​​​​​​​        ... ...
        table.removebyvalue(coTable, co)
end)
table.insert(coTable, co)

我试过在remove后直接将co=nil,insert时检查co~=nil再进行,还是会有异常情况。
如果Lua协程本身是没有对象池缓存机制的,那就不会存在我说的问题。

实际上这个问题就是对象池的坑,只是演变到了协程这里让人很抓狂 


http://www.kler.cn/a/315824.html

相关文章:

  • 前端开发中常用的包管理器(npm、yarn、pnpm、bower、parcel)
  • AutoCad 无界面开发
  • Sigrity SPEED2000 Power Ground Noise Simulation模式如何查看PDS系统的自阻抗操作指导
  • Spring MVC 与 JSP 数据传输
  • 【pytorch】常用强化学习算法实现(持续更新)
  • 如何用WordPress和Shopify提升SEO表现?
  • 云盘视频保护神器,支持云盘视频加密与在线播放,配合alist使用,超完美!
  • react + antDesignPro 企业微信扫码登录
  • MySQL缓冲池详解
  • react router v6
  • LLaMA-Factory 使用 alpaca 格式的数据集
  • 【Delphi】通过 LiveBindings Designer 链接控件示例
  • Java笔试面试题AI答之设计模式(5)
  • affine: python仿射变换包
  • 【题解】—— LeetCode一周小结38
  • 解决RabbitMQ设置x-max-length队列最大长度后不进入死信队列
  • 周邦彦,北宋文坛的独特乐章
  • 前端工程化4:从0到1构建完整的前端监控平台
  • 自动化生成与更新 Changelog 文件
  • 花生壳、神卓互联等主流内网穿透技术分享
  • FTP服务
  • 编译 Android 11源码
  • 人工智能(AI)的影响下人类的生活样子
  • Shell 脚本学习
  • STM32 单片机最小系统全解析
  • Vue子组件样式受到父组件污染