9.3.3 多线程编程的应用
线程原本是操作系统中的概念,是操作系统用于实现系统功能的工具。现在线程已演变成为用户程序可使用的工具,广泛用于应用程序设计。 多线程技术主要用于需要并发执行的场合。例如在很多游戏程序中,都需要维持一个动画场景,而玩家可以通过鼠标或键盘来输入操作指令,控制游戏的进行。假如程序只有一个 控制流,则当程序执行到等待用户输入指令的时候,由于用户输入较慢(相对 CPU 速度来 说),程序无法向前继续执行语句,因而无法更新动画画面,效果上动画就停顿了。如果将 等待用户输入的任务和维持动画的任务用两个线程来独立实现,则可解决这个问题。
上述例子其实具有一般性。如果在一个长时间计算任务(维持动画)期间需要对输入输 出事件(鼠标或键盘指令)做出反应,单线程程序是不行的,因为程序会阻塞在长时间计算 任务上,没有机会来检查输入输出。而如果用一个线程来执行这个长时间计算任务,并让另 一个线程监控输入输出事件,两个线程的并发执行就可以使应用程序在执行计算任务的同时 能对用户输入作出反应。如图 9.2 所示。
图 9.2 多线程的应用
此外,在科学计算中,很多数值算法都可以并行化,如矩阵的并行计算、线性方程组的 并行求解、偏微分方程的并行求解和快速傅里叶变换的并行算法等等。这时可以为每个处理 器建立一个线程,从而高效地进行计算。
虽然多线程技术有很多用途,但掌握多线程编程有点难度,即使对职业程序员也是如此。 例如,多线程技术涉及所谓竞态条件(race condition),即因为未曾预料到的、对事件之间 相对时序的严重依赖而导致的异常行为。具体例子如:两个客户同时登录订票网站,都看到 某航班还剩一个座位,于是都下单预定该座位,最终必然会因为谁先来后到而引起纠纷。如 果两人是在售票点排队购票(串行执行)就没有这个问题。因此,多线程程序与串行程序是 不同的,需要分析并协调各线程间的复杂的执行时序,这导致编程和调试都很困难。
多线程程序中,由于各线程是相互独立的,它们的并发执行没有确定次序可言,因此线 程是一种非确定性的计算模型,同一个程序的多次执行未必导致同样的结果。所以,多线程 计算模型不具有串行计算模型的可理解性、可预测性和确定性性质,使用时要非常小心。