最近饱受多线程的折磨 -_-,大概在多线程编程方面太缺乏经验了,经历了一个痛苦的转变。。。
常常会发现服务器宕机了,在一个莫名其妙,看起来永远不会宕机的地方,苦苦思索几天几夜也找不到原因,最后发现是多线程在捣鬼
服务器进程架构是这样的,每个进程都由2个线程组成:
1个主线程,负责消息的收发成,以及进程的启动、停止;
1个timetick线程,负责消息的处理
逻辑看起来很简单,可由于加入了大量大量单例模式的应用,就悲剧的变得复杂起来
消息的读取:主线程和timetick线程共享一个recv消息队列,主线程负责以字节流的形式从socket接口中读取最原始数据,然后初步解析并封装成一个一个消息包的形式push到recv消息队列中。timetick线程从recv消息队列中将消息包逐个pop出来并执行,这个pop并不是收到消息就实时执行的,而是在线程的每个逻辑循环里执行一次。毫无疑问,此recv消息队列一定要加锁的。
消息的发送:有了recv消息队列,当然就有send消息队列,为了响应速度,这个send消息队列是实时的,有需要就立即发送,所以,它没有加读写锁(嘿嘿,不加锁其实还为了多提高点点程序效率,因为消息的发送太频繁了,又是实时发送的,在一个逻辑循环的过程中,就可能有n个消息需要发送)。就这样,悲剧发生了,就在这以微秒计算的时间内,主线程和timetick修改了同一个recv消息队列,程序宕机了,不太频繁的,一天宕一次,或者2天宕一次,或者一周宕一次。。。呵呵,处理的方法有点狡猾,不是给recv消息队列加锁,而是把需要send的消息包,以recv消息包的方式放到recv消息队列中,然后timetick线程在解析的时候将需要send的消息包再push进send消息队列,这样,主线程就不再直接接触send消息队列了,send消息队列也不会被多线程操作了
经历过数个从宕机的恶梦中醒来的夜晚,经历过无数玩家喷的口水,总算让服务器安静了下来
现在如果服务器还莫名其妙的宕机,如果还是多线程在捣鬼,也许,我能从其中看出一点点线索了。。。^_^
常常会发现服务器宕机了,在一个莫名其妙,看起来永远不会宕机的地方,苦苦思索几天几夜也找不到原因,最后发现是多线程在捣鬼
服务器进程架构是这样的,每个进程都由2个线程组成:
1个主线程,负责消息的收发成,以及进程的启动、停止;
1个timetick线程,负责消息的处理
逻辑看起来很简单,可由于加入了大量大量单例模式的应用,就悲剧的变得复杂起来
消息的读取:主线程和timetick线程共享一个recv消息队列,主线程负责以字节流的形式从socket接口中读取最原始数据,然后初步解析并封装成一个一个消息包的形式push到recv消息队列中。timetick线程从recv消息队列中将消息包逐个pop出来并执行,这个pop并不是收到消息就实时执行的,而是在线程的每个逻辑循环里执行一次。毫无疑问,此recv消息队列一定要加锁的。
消息的发送:有了recv消息队列,当然就有send消息队列,为了响应速度,这个send消息队列是实时的,有需要就立即发送,所以,它没有加读写锁(嘿嘿,不加锁其实还为了多提高点点程序效率,因为消息的发送太频繁了,又是实时发送的,在一个逻辑循环的过程中,就可能有n个消息需要发送)。就这样,悲剧发生了,就在这以微秒计算的时间内,主线程和timetick修改了同一个recv消息队列,程序宕机了,不太频繁的,一天宕一次,或者2天宕一次,或者一周宕一次。。。呵呵,处理的方法有点狡猾,不是给recv消息队列加锁,而是把需要send的消息包,以recv消息包的方式放到recv消息队列中,然后timetick线程在解析的时候将需要send的消息包再push进send消息队列,这样,主线程就不再直接接触send消息队列了,send消息队列也不会被多线程操作了
经历过数个从宕机的恶梦中醒来的夜晚,经历过无数玩家喷的口水,总算让服务器安静了下来
现在如果服务器还莫名其妙的宕机,如果还是多线程在捣鬼,也许,我能从其中看出一点点线索了。。。^_^