1.5 线程和共享内存

一个执行的程序(称为进程)可能有很多子程序组成,并且这些子程序都有独立的控制流。当该进程启动时,这些子程序就并发的开始执行。这些子程序可以称之为线程。进程中的所有线程都会共享一些资源(比如:内存、打开的文件、全局变量),不过他们也有属于自己的资源(比如:堆栈、自动变量)。线程使用全局共享地址空间分配出的变量进行通讯。通讯时需要有同步机制来保证同一个内存区域的内容,不会被多个线程更新。

具有共享内存的系统中,所有的处理器都能访问到同一地址空间(比如:能看到同一个全局变量)。共享内存模型中一个关键的特性,就是不需要编程者去管理数据的移动。在这样的系统中,线程如何去更新全局变量,底层硬件和编程者要达成共识,并遵守相关的访问协议。“相关协议”的学术名称为“内存一致性模型”,内存一致性模型已经被很多高级语言所支持,比如:Java、C/C++11和OpenCL。相关的高级结构有互斥量和信号量,以及“获取-释放”语义。程序员会显式告知底层硬件需要使用哪种同步方式,从而能让硬件更加高效的执行并发任务。

随着处理器数量的增加,底层硬件也要花费很大的精力来对共享内存进行支持和管理。总线的长度(与延迟和功耗相关),硬件结构上接口的数量,以及共享传输总线的数量都将占用很多资源。当我们尝试增加处理器的数量时,这些额外的硬件设备数量将会呈指数级别增长。我们的系统将变得更复杂,同时也增加了很多的额外开销。这些是多核或多处理器系统的弊端,并且这也限制着一起工作处理器的数量。内存一致性模型下,能够使用的处理器相对较少,这是因为共享总线和相干性协议将会成为性能瓶颈。系统中多一些松散的共享内存,相对来说会好一些;当有成规模的内核在共享内存系统中时,其会让系统变得复杂,并且内核间的互相通讯也要付出很高的代价。大多数多核CPU平台都支持某一种共享内存,OpenCL也可以在支持共享内存的设备上运行。