用户工具

站点工具


cmud:hints:cmud的全局变量-多线程和event

Cmud的全局变量、多线程和Event

出品人:Seagate

原帖地址:Cmud的全局变量、多线程和Event

从上周末到现在转入Cmud差不多快一周时间了,从Zmud的单线程架构 转换到Cmud的多线程架构,不能说自己现在对Cmud有多了解,但是经过 mister,killunix等人的帮助下也算稍微有点了解了。现在谈谈Cmud特色 的一些地方。Cmud比起Zmud有特色的地方很多,太多地方没弄明白。不过 这几天被Cmud的多线程架构折磨,算是有一点点个人理解。仅在这里抛砖 引玉,如果下面描述有误请多加提点。

说起Cmud的多线程架构首先要注意的就是他的全局变量,由于是多线 程架构,所以全局变量很容易被两个以上线程共享,这时候你使用全局变 量就要非常注意。有一个很好的办法就是#section语法,这个语法就是对 变量提供保护区,在这个保护区内用到的全局变量会加锁,其他线程要用 到这个变量就要等#section {commands}解锁以后才能用。关键点在于你 修改全局变量或者防止其他线程修改你的全局变量的时候就需要对这个区 域加锁。但是这里衍生出另外一个热门话题就是死锁问题。举例来说:

    #trigger {A} {#section {#va var1 1;#if @var2>1 {commands}}
    #trigger {B} {#section {#va var2 1;#if @var1>1 {commands}}

当这两个触发同时运行的时候就会产生问题,由于触发A对var1变量加锁, 但是要等待触发B对var2解锁才能执行下一步,而触发B对var2变量加锁, 但是要等待触发A对var1解锁才能执行下一步,两个语句互相等待资源, 就导致程序陷入死循环,当然也就完蛋了!你如果用#thread查看的时候 就会发现问题。所以总的来说为了保护全局变量的一致性需要用#section 保护你的关键代码,但是不能多加,还有就是为了避免使用全局变量,最 好多用local变量,这种变量没有多线程竞争问题,但是local变量只能在 一个限定环境内执行,不能跨线程或者跨区域使用,多线程之间信息交流 还是要靠全局变量。

多线程从上面看来引出了一大堆麻烦事情,看上去没有多少好处,但 是多线程不是没有优势的,在这里Cmud提供了Event机制和信号量。(其他 多线程好处没研究透,昨天开始看Event发现还是不错的东西)在Zmud时代 你要在多个触发语句之间做协调需要用到很多全局变量进行赋值或者用一些 set action “触发条件”,#sa 触发条件来处理并发,这些协调总的来说会 有很多问题,常常出现协调不一致,或者显示输出混乱导致触发停止,问题 不一而足,反正非常麻烦。利用Cmud的多线程机制和Event就可以很好的解 决这些问题。举例来说你战斗的时候可以用一个

           #alarm {0.5} {#raise onPerform}

来不停的触发发特殊技能事件,具体事件onPerform可以处理怎么发技能, 然后在有一个#trigger {战斗返回信息} 来处理是应该停止或者启动onPerform 事件。关闭事件了#raise发起事件也就无效了,战斗也停止了。这种交互就 节约了大量处理触发引起的一些列问题,提高了系统稳定性。Event还有一个 用途就是你在处理过程中主动发起一个事件处理,然后主线程用#waitsign来 等待一个信号量,事件处理完毕发起一个信号量,这样子就可以在一个触发 语句里面实现并发处理,而且不影响同步。Event中另外一个有点就是系统提 供了大量自动事件,有时候你用系统行走结束用onWalkEnd事件,房间相关有 onRoomEnter,onRoomWalk等事件方便处理,就不需要用触发来判断了,简 化了你做遍历算法的时候编码复杂度。至于Event其他好处就需要大家一起 挖掘了。


后续讨论

  • Jason:cmud引入多线程却不支持协程真是昏了
  • Seagate:可以用信号量来进行线程间同步。不过有时候关键是不知道啥时候变成多线程了。所以除非你自己创建两个显式线程,否则用信号量同步难度也非常大。他还有一个同步方式是#waitthread,但是不知道怎么知道线程ID,不知道是不是可以显示创建一个带id的线程。这个东西比较麻烦。反正他的线程间全局变量没有自动加锁确实很恶心,正常来说全局变量的同步应该是内核处理的,用户只需要考虑少量的线程间同步就可以,现在cmud的情况就是大多数全局资源的锁他都不管,都要用户来处理。所以造成非常多的锁冲突,而且用户自己加锁一不小心就会变成死锁,cmud本身也没有死锁的解锁机制。我自己就碰到好几次。
  • killunix:所以说,用section一定要小心,他的帮助文件里写的很清楚,cmud的开发人员也谈过这个问题,新版本不知有没有解决。在处理多个触发之间关系的时候,建议你用%trigg()这个函数,很方便
  • killunix:#alarm 可以和%alarm结合起来,创建复杂的alarm
cmud/hints/cmud的全局变量-多线程和event.txt · 最后更改: 2020/08/15 21:40 (外部编辑)