6.4 多线程与多进程

作为一种相对较新的并发编程方式,多线程编程有着明显的优势。这些优势成为不断诱惑着我们采用这种方式进行并发编程的重要因素之一。不过,对于多线程编程来说,它的优势之处很可能也隐含着一些劣势。这种微妙的差别使得我们在二者选其一的时候总是需要仔细的考量一番。

我们已经知道,在多个线程之间交换数据是非常简单和自然的事情。而在多个进程之间,我们只能通过一些额外的手段(比如管道、消息队列、信号灯和共享内存区)在它们之间传递数据。显然,使用这些额外的手段会增加开发的成本。不过,线程间交换数据虽然简单但却由于可能发生竞态条件而不得不使用一些同步工具(比如互斥量和条件变量)加以保护。这些与业务逻辑无关的代码会增加程序的复杂度。并且,使用这些同步工具本身也是需要注重方式方法的。如果使用不当,可能造成程序性能的大幅下降甚至发生死锁。这其中充满着各种博弈。因此,在进行多线程编程的时候,我们要仔细地划分临界区,并在对实际情况进行评估之后,再在原有代码上添加互斥量和条件变量的相关操作,以求同步的正确和高效。

并发编程方式的选择对程序的开发维护成本和运行性能都有着深远的影响。总体来说,多线程作为更加现代的并发编程方式在系统资源的利用和程序性能的提高方面都更具有优势。但是,在某些情况下(比如对信号的处理、同时运行多套不同的程序以及包含多个需要超大内存支持的任务等),传统的多进程编程方式可能会更加适合。

选择并发编程方式的一个不可被忽视的因素就是我们所使用的编程语言。一些编程语言更适合编写多进程程序,而另一些编程语言则对多线程有着强大的支持。Go语言是两者兼而有之但更倾向于后者的。它对多线程技术的使用比现有的其他编程语言更加先进和充分。

虽然每种编程语言都会倾向于某种并发编程方式,但是它们的最终目标都是在开发维护成本和运行性能这两个方面上进行权衡,以满足应用开发者的要求。需要注意的是,程序的开发维护成本的降低和运行性能的提高在很多时候是相互对立的。它们之间常常存在着此消彼长的态势。所以,让程序在可容忍的开发维护成本下被高效的并发运行并不是一件容易的事。我们在编写并发程序的时候总是应该仔细考量并小心对待。

Go语言的先进特性可以让我们非常快速地开发应用程序。同时,它的简约编程风格和工程哲学也让应用程序的维护成本总能保持在较低的水平上。更重要的是,Go语言程序的运行性能已经与传统的系统级别编程语言相差无几了。Go语言天生就是被用来编写并发程序的。它完全可以胜任适合采用多线程编程方式的所有应用场景。并且,一些不适合在多线程程序中执行的任务(比如信号处理)它也可以很容易地完成。总之,使用Go语言编写并发程序能够帮助我们更快速和轻松地达到目标。