多线程并非万金油
为了发挥多核机器的威力,可以用多进程或多线程的办法,由于多进程往往涉及共享内存等IPC问题,所以很多人都倾向于选择多线程,并以此为灵丹妙药。但多线程并非万能,它虽然使用方便,却也有硬伤——线程一死,会牵连其它。孙子曰“不尽知用兵之害者,则不能尽知用兵之利也”,不了解多线程的缺点,也就不能很好的使用它。
我们项目中有一个daemon,功能是转发并处理消息,为了能看到daemon运行的细节,我们还做了一个monitor线程,由该线程通过某个端口提供简单的web服务,这样就可以直接用浏览器查看daemon的运行状态(比如处理了多少消息,丢弃了多少等)。后来,monitor线程出现了一个bug,造成线程挂掉——于是造成了整个daemon挂掉。这下郁闷了,daemon本身是很重要的,而monitor是不那么重要的,现在是次要部分的bug拖累了重要部分的运行。
这就是多线程程序的缺陷。如果多个线程做的是同样的事情,那还尚可;但如果多个线程,有的做这件事,有的做那件事,而且事情的重要程度不同,那不重要的线程由于代码错误或其他原因死了,其它的线程——包括执行重要功能的——也只能跟着挂。这在健壮性上肯定是不好的。apache采用多进程应该也是出于这样的考虑,因为它的module可能是用户自己写的,可能并不稳定,但由于module不稳定而挂掉整个apache,显然不应该。当然,apache2开始支持多线程,但即使这样,它默认还是多进程的,并没有整个倒向多线程。
也许有人会说:你代码写好一点,不要有bug,多线程不就没事了吗?首先,我们讨论的是软件健壮性的问题——怎样在坏了一部分以后其它部分还能工作,而不是软件正确性的问题——怎样写正确的代码。不是一个方向的问题,并不矛盾。其次,软件不可能没有bug,我们如果能把不同杀伤性的bug通过不同进程把它们隔开,就能降低影响,这跟挖掘bug的目标是一致的——都是为了增加软件的可用性。
所以,多线程并非万金油。为了健壮性,可以考虑把不同性质的任务分到不同的进程上,再由父进程统一管理。而在这些进程之下,可以再有多线程。当然,这样开发就复杂了。
相关文章
- 客服琐记 - 08 12, 2010
- fedora 9 小集 - 01 05, 2009
- 多线程调试 - 12 17, 2008
如果 monitor 的功能在 daemon 的(主)线程里实现(执行),它的 bug 同样会导致 daemon 挂掉。一样是“次要部分的 bug 拖累了重要部分的运行”,跟多线程没关系。
我的意思是monitor应该是daemon的一个子进程,这样monitor就算挂了,daemon也不会有事。
刚才看了一篇数据库的拆分
这也相当于进程/线程的水平分割和垂直分割吧?
万变不离其宗啊~~~
受教
好像不太一样,数据库垂直分割是因为单机存不下了,多进程是为了健壮性。
受教,多进程也不一定好,多线程也不一定好,具体问题得具体分析,没有银弹
“没有银弹”!
确实各有利弊啊,之前公司是开发的内存库是多线程的,只要某个线程一挂,整个系统都要重新上电,加载,重建索引,影响业务好几分钟,如果数据量大的话几十分钟也是常事。
现在单位使用的是多进程的技术,采用共享内存,这样子某个进程挂了,只要监控进程在那么重新拉起也就是几秒钟的事情。好处不说自明。
google的chrome同样也是采用的多进程技术,当某个页面非法down了不至于我的其他页面也跟着歇菜,使用效果很好.