在单CPU上使用多线程
假设我们略微修改我们的例子,让它能演示有些时候在单处理器上使用多线程的好处。
在这个修改的例子里面,网络中的一个节点负责计算扫描线(与前面的图像例子一样)。不过,当一个扫描线的计算结束后,它的数据就通过网络发送到另外一个节点。下面是我们修改后的main()函数:
假设我们略微修改我们的例子,让它能演示有些时候在单处理器上使用多线程的好处。
在这个修改的例子里面,网络中的一个节点负责计算扫描线(与前面的图像例子一样)。不过,当一个扫描线的计算结束后,它的数据就通过网络发送到另外一个节点。下面是我们修改后的main()函数:
我们前面的使用房子做的比喻对于解释同步的概念是非常合适的,但对系统中另一个重要方面就不合适了。在我们的比喻中,多个线程是同时运行的。可是,在实际的系统中,一般只有一个处理器,那么在一个时间点上只能运行一件“事”。
下面看看在实际系统中的真实运行情况,在较“经济”的情况下,一个系统中只有一个中央处理器。这时,在任何时间点就只能有一个线程可以运行。系统内核使用数种规则来决定让哪个线程运行并运行该线程。
如果你购买的计算机有多个、相同的CPU,并且这些CPU共享内存与设备,那么就可以说你有了一个SMP系统了(SMP是对称多处理器的简称,指系统中的这些处理器是一样的)。这时,可以同时运行的线程的数量就受限于CPU的个数了。由于一个CPU一次只能运行一个线程,在有多个CPU的情况下,多个线程就可以同步运行。
共享内存提供了进程间通信所能实现的最高带宽。一个共享内存对象创建之后,可以访问这个对象的进程就能够使用指针直接对其读写。这就意味着,共享内存访问本身就是非同步的。如果一个进程更新共享内存的一个区域,就必须特别小心不要让其他进程读取或更新同一块区域。即使是最简单的读取操作时,其他进程仍然有可能读到变化与不稳定的数据。
为了解决这个问题,共享内存就常与其他同步原(synchronization primitives)结合在一起使用以使进程之间的内存更新原子化。如果更新的间距很小,同步原就会限制自己固有的使用共享内存的高带宽。共享内存用于以块的模式更新大量的数据是最有效的。
信号量(semaphores)与互斥体(mutexes)都是适用与共享内存结合使用的同步原。信号量是在创建进程间同步的POSIX实时标准时引入的。互斥体则是在创建线程同步的POSIX标准是引入的。互斥体也可以在不同进程中的线程之间使用。POSIX将其作为一个可选的能力,我们在这里则是支持的。一般来说,互斥体要比信号量效率更高。
共享内存与消息传递可以结合起来以提供支持以下功能的IPC:
近期评论