就爱来小说网

第九章 冲刺期的第一个Bug(3/5)



    这一次,Bug在第三次测试时就出现了。世界卡在0.3倍慢放,李师傅的动作像在水里走路,一帧一帧地挪。日志文件滚屏,他一行行看,眼睛发酸。

    忽然,他注意到一行奇怪的日志:

    [TimeSystem] Thread conflict detected at timestamp 120.5s.

    [RenderThread] Acquired lock at 120.5001s.

    [TimeThread] Acquired lock at 120.5001s.

    时间戳完全一样。两个线程,在同一毫秒内,获取了同一把锁。理论上不可能,除非系统时钟精度不够,或者锁的实现有漏洞。

    他查代码。用的是标准的CRITICAL_SECTION锁,Windows自带的,不应该有问题。除非……他想到一个可能性:在“无事可做”状态下,时间系统会分裂成两条时间轴,每条时间轴都有自己的锁。当玩家退出静止状态,两条时间轴要合并时,需要同时获取两把锁。如果获取顺序不对,可能死锁。

    他翻到合并逻辑的代码。果然,写成了:

    lock(timeLock_室内);

    lock(timeLock_窗外);

    // 合并逻辑

    unlock(timeLock_窗外);

    unlock(timeLock_室内);

    而另一个地方,渲染线程更新窗外光影时,顺序是:

    lock(timeLock_窗外);

    lock(timeLock_室内);

    // 更新逻辑

    unlock(timeLock_室内);

    unlock(timeLock_窗外);

    经典的死锁条件:线程A锁了1,等2;线程B锁了2,等1。平时很难触发,因为两个线程很少同时卡在这个点上。但在“无事可做”状态下,时间系统频繁分裂合并,渲染线程又要频繁更新窗外光影,撞上的概率就大了。

    他修改代码,强制统一锁的获取顺序:永远先锁室内,再锁窗外。重新编译,运行测试程序。

    跑完十次,没出现Bug。二十次,没出现。五十次,还是没出现。

    他长舒一口气,把修复方案提交到SVN,在群里@陈末:“时间Bug可能解决了,是锁顺序的问题。你那边跑一下压力测试看看。”

    陈末半小时后回复:“跑了二百次,零复现。应该是修了。但合并逻辑我优化了一下,减少了锁的持有时间,性能提升15%。新代码提交了。”

    李君宪看着那条消息,忽然笑了。这就是团队的感觉:你解决一个问题,队友把它变得更好。像接力赛,一棒传一棒,朝着同一个终点。

    窗外的天黑了。宿舍楼响起喧闹声,晚课的学生回来了。王浩推门进来,拎着两份炒面:“李哥,给你带了饭。别饿死了。”

    “谢了。”李君宪接过,塑料饭盒还烫着。他掰开一次性筷子,扒了两口,油重盐也重,但很香。他边吃边看群,林薇发了遮罩图的最终版,叶晚回复说锯齿问题在她电脑上也不见了,苏语说预生成的音频做好了,内存占用28MB,没超预算。

    一切都在向前走。虽然慢,虽然难,但在走。

    吃完饭,他打开博客。好几天没更新了,后台有读者留言催更:“博主还活着吗?”“是不是放弃了?”“募捐了八千多,可别跑路啊。”

    他新建文章,标题:
>

本章未完,点击下一页继续阅读