进程与线程
为什么对于大多数合作性任务,多线程比多个独立的进程更优越呢?这是因为,线程共享相同的内存空
间。不同的线程可用存取内存中的同一个变量。所以,程序中所有的线程都可以读或者写声明过的全局变量。
如果曾用fork()编写过重要代码,就会认识到这个工具的重要性。为什么呢?虽然fork()允许创建多个进程,
但它还会带来以下通信问题:如何让多个进程相互通信,这里每个进程都有各自独立的内存空间。对于这个问
题没有一个简单的答案。虽然有许多不同种类的本地IPC(进程间通信),但它们都遇到两个重要障碍。
- 强加了某种形式的额外内核开销,从而降低性能;
- 对于大多数情形,IPC不是对于代码的“自然”扩展。通常极大地增加了程序的复杂性;
双重坏事:开销和复杂性都非好事情。如果曾经为了支持IPC而对程序大动干戈过,那么您就会真正欣
赏线程提供的简单共享内存机制。由于所有的线程都驻留在同一内存空间,POSIX线程无需进行开销大而复
杂的长距离调用。只要利用简单的同步机制,程序中所有的线程都可以读取和修改已有的数据结构。而无需
将数据经由文件描述符转储或挤入紧窄的共享内存空间。仅此一个原因,就足以让您考虑应该采用单进程/
多线程模式而非多进程/单线程模式。
为什么要用线程?
与标准fork()相比,线程带来的开销很小。内核无需单独复制进程的内存空间或文件描述符等等。这就
节省了大量的CPU时间,使得线程创建比新进程创建快上十到一百倍。因为这一点,可以大量使用线程而无
需太过于担心带来的CPU或内存不足。使用fork()时导致的大量CPU占用也不复存在。这表示只要在程序中有
意义,通常就可以创建线程。
当然,和进程一样,线程将利用多CPU。如果软件是针对多处理器系统设计的,这就真的是一大特性
(如果软件是开放代码,则最终可能在不少平台上运行)。特定类型线程程序(尤其是CPU密集型程序)的
性能将随系统中处理器的数据几乎线性地提高。如果正在编写CPU非常密集型的程序,则绝对想方设法在代
码中使用多线程。一旦掌握了线程编码,无需使用繁琐的IPC和其他复杂的通信机制,就能够以全新和创造
性的方法解决编码难题。所有这些特性配合在一起使得多线程编程更有趣、快速和灵活。
什么是线程?
- 专业点说法,线程被定义为一个独立的指令流,它本身的运转由操作系统来安排,但是,这意味着什么呢?
- 对软件开发者来说,解释线程最好的描述就是“procedure”,可以独立于主程序运行;
- 再进一步,设想一个包含了大量procedure的主程序,然后想象所有这些procedure在操作系统的安排下一起或独立的运行,这就是对于多线程的一个简单描述;
- 问题时,它是如何实现的呢?
- 在弄懂线程之前,第一步要搞清楚Unix进程。进程被操作系统创建,并需要相当多的“开支”,进程包含如下程序资源和程序执行状态信息:
- 进程ID,进程群组ID,用户ID,群组ID
- 环境
- 工作目录
- 程序指令
- 寄存器
- 栈
- 堆
- 文件描述符
- 信号动作
- 共享库
- 进程间通信工具(例如,信号量、共享变量、管道、消息队列)
- 线程使用和在进程内的生存,仍由操作系统来安排并且独立的实体来运行,很多程度上是因为它们为可执行代码的存在复制了刚刚好的基本资源。
- 这个独立的控制流之所可以实现,是因为线程维护着如下的东西:
- 栈指针
- 寄存器
- 调度属性
- 等待序列和阻塞信号
- 线程拥有的数据
- 所以,总的来说,Unix环境里的线程有如下特点:
- 它生存在进程中,并使用进程资源;
- 拥有它自己独立的控制流,前提是只要它的父进程还存在;
- 它仅仅复制可以使它调度的必要的资源;
- 它可能会同其他与之同等的独立的线程分享进程资源;
- 如果父进程死掉,那么它也会死掉——或者类似的事情;
- 它是轻量级的,因为大部分的开支已经在它的进程创建时完成了;
原文:http://www.cnblogs.com/blueclue/archive/2010/07/16/1778855.html
感谢作者。
梦醒潇湘love
2012-12-10 16:04