类型系统线程安全
最近情绪有点失控,跟很欣赏的同事吵架了,真难过。有些话,可能真的只有吵架才会说出口,只好安慰自己,这未尝不是一次难得的交流。究其原因,就是一段代码由我开发,他接手维护,然后交给我继续跟进;最近频繁报bug,他觉得在替我擦屁股,收拾代码,我也觉得我在替他擦屁股,大家心里有气,但是谁也没有说出口。多点面对面交流,多点讨论,工作压力小一点,可能就可以避免了。
最近修复的dbd的bug,一个是字符串管理上面的,上一篇博文已经提到了mapping_to_bson的,这周还发现了bson_to_mapping过程中的问题。由于dbd的对象管理采用了LPC虚拟机带的那套,包括hash表和字符串管理,而这套东西默认是在单线程运行的,没有考虑线程安全,所以dbd作为唯一一个多线程运行的进程,就有线程安全的隐患了。我翻看了原始实现,在替换mongodb前,dbd实现反序列化的时候,很机智的避开了共享字符串,不管这个用作mapping key的字符串是否已经使用过,直接从系统里分配内存。我理解另一位同事用共享字符串的理由,维基里提到string interning,就是为了节省内存和时间。因为dbd作为玩家数据的缓存,存储的玩家一定有很多key是相同的,这部分内存如果节省下来应该蛮可观的。为了线程安全,可能需要牺牲掉这个优化了。
另外一个是mapping结点的管理。新建mapping结点的时候,会从一个mapping空闲结点池里取,如果没有空结点则malloc一个新的,放到池里,最后从池里取。由于这个空结点池是全局的,没有加锁保护,同样会导致多线程上出现问题。如果不用锁,就只能像string那样,不依赖自己实现的结点池,每次使用均向系统申请了。但如果加锁,由于gamed这个游戏逻辑引擎也会用到,到时候就有可能影响游戏逻辑的运行效率了。
但是,反观最近的修改,除了通过网络将dbd的数据打到mongo去,其余与最早的实现差别不多,字符串那个问题可以说是共享字符串引起,为什么mapping这个冲突问题以前没有暴露呢?我留意了一下原有的锁设置。原有的全局锁是一把pthread的读写锁,在接到gamed发过来的脏数据后,往脏数据队列里插入,这时候会加上写锁。如果写锁加上了,读锁自会处于等待状态。当写锁释放,读锁加上的时候,可以有多个读线程同时读。这时候,应该有可能出现读线程之间同时创建mapping的情况啊,为什么当时会没出现问题呢?待查
目前看来,只要在这些涉及到全局变量的点上,主要是mapping和字符串管理,加上可靠的锁保护,应该能够有效解决线程冲突的问题。只是,前提是能够重现线程冲突这个bug……
posted on 2013-10-21 00:42 lifehacker 阅读(645) 评论(0) 编辑 收藏 举报