2009年2月8日星期日

解耦合手段之六:并发






什么?并发也是一种解耦合的手段么?
是的。
一般的程序都是顺序执行的,在这种情况下,程序的执行和执行的时间是相互依赖的或者说是耦合的。当这种耦合成为一种阻碍时我们就需要并发(Concurrency)。
"Concurrency is a decoupling strategy. It helps us decouple what gets done from when it gets done."
 --Clean Code, Robert C. Martin

一个很常见的错误观点是并发总是能够提高性能。这在大多数情况下,尤其是单核系统中往往是不成立的,就像1+1+1+1+1和1*4都等于4一样。
我能想象到的采用并发的理由总结一下有以下几点:
  • 解开what和when的耦合以后,程序的结构更容易被理解。例如用一个大的循环来处理所有用户的聊天请求,就不如用不同的线程来处理每个用户的请求那么清晰,而且也更方便扩展对用户的服务。
  • 需要提高响应输入的速度,或及时的输出中间结果。
  • 需要利用多核,多CPU,多个机算机甚至网络的计算能力。
并发就需要用到多线程或者多进程。而在多线程或多进程编程的时候我们往往又需要或不得不把其它耦合性带回到程序里去。例如对共享数据的操作需要互斥,有些业务逻辑要求有顺序,同时还要避免可能发生的死锁。因此,结果可能是我们引入了更多的耦合性。例如前面提到的聊天程序。因为每个请求都很简单,处理得很快,因此即使是上千用户一起使用单一线程的服务也是感觉不到有什么问题。然而采用多线程处理就要引入很多其它负载,反而可能降低性能或引入更多问题。但如果每个用户的服务内容很复杂,单一线程又会变得很难理解或很难处理。
这个时候,合理的选择串行和并发以及并发的手段就成为降低耦合性的关键。如果我们不得不选择并发,那么提高每个进程的内聚性仍是降低整体耦合性的有效手段。

现在有很多并发语言,例如传统的电信行业中使用的SDL,还有新的语言如Erlang, Stackless Python。它们往往会提供高效的进程调度机制,方便的进程间通信手段以及合理的互斥方法。但无论使用什么语言,在多么先进的框架下工作,并发编程都是非常复杂的,并且和串行的编程所需要用到的设计策略往往是完全不同的。


没有评论:

发表评论