在.NET多线程编程这个系列我们将一起来探讨多线程编程的各个方面。
首先我将在本篇文章的开始向大家介绍多线程的有关概念以及多线程编程的基础知识;在接下来的文章中,我将逐一讲述。NET平台上多线程编程的知识,诸如System.Threading命名空间的重要类以及方法,并就一些例子程序来作说明。
引言
早期的计算硬件十分复杂,但是操作系统执行的功能确十分的简单。那个时候的操作系统在任一时间点只能执行一个任务,也就是同一时间只能执行一个程序。
多个任务的执行必须得轮流执行,在系统里面进行排队等候。由于计算机的发展,要求系统功能越来越强大,这个时候出现了分时操作的概念:每个运行的程序占有一定的处理机时间,当这个占有时间结束后,在等待队列等待处理器资源的下一个程序就开始投入运行。
注意这里的程序在占有一定的处理器时间后并没有运行完毕,可能需要再一次或多次分配处理器时间。那么从这里可以看出,这样的执行方式显然是多个程序的并行执行,但是在宏观上,我们感觉到多个任务是同时执行的,因此多任务的概念就诞生了。
每个运行的程序都有自己的内存空间,自己的堆栈和环境变量设置。每一个程序对应一个进程,代表着执行一个大的任务。一个进程可以启动另外一个进程,这个被启动的进程称为子进程。父进程和子进程的执行只有逻辑上的先后关系,并没有其他的关系,也就是说他们的执行是独立的。
但是,可能一个大的程序(代表着一个大的任务),可以分割成很多的小任务,为了功能上的需要也有可能是为了加快运行的速度,可能需要同一时间执行多个任务(每个任务分配一个多线程来执行相应的任务)。
举个例子来说,你正在通过你的web浏览器查看一些精彩的文章,你需要把好的文章给下载下来,可能有些非常精彩的文章你需要收藏起来,你就用你的打印机打印这些在线的文章。在这里,浏览器一边下载HTML格式的文章,一边还要打印文章。这就是一个程序同时执行多个任务,每个任务分配一个线程来完成。因此我们可以看出一个程序同时执行多个任务的能力是通过多线程来实现的。
多线程VS多任务
正如上面所说的,多任务是相对与操作系统而言,指的是同一时间执行多个程序的能力,虽然这么说,但是实际上在只有一个CPU的条件下不可能同时执行两个以上的程序。
CPU在程序之间做高速的切换,使得所有的程序在很短的时间之内可以得到更小的CPU时间,这样从用户的角度来看就好象是同时在执行多个程序。
多线程相对于操作系统而言,指的是可以同时执行同一个程序的不同部分的能力,每个执行的部分被成为线程。所以在编写应用程序时,我们必须得很好的设计以 避免不同的线程执行时的相互干扰。这样有助于我们设计健壮的程序,使得我们可以在随时需要的时候添加线程。
线程的概念
线程可以被描述为一个微进程,它拥有起点,执行的顺序系列和一个终点。它负责维护自己的堆栈,这些堆栈用于异常处理,优先级调度和其他一些系统重新恢复线程执行时需要的信息。从这个概念看来,好像线程与进程没有任何的区别,实际上线程与进程是肯定有区别的:
一个完整的进程拥有自己独立的内存空间和数据,但是同一个进程内的线程是共享内存空间和数据的。一个进程对应着一段程序,它是由一些在同一个程序里面独立的同时的运行的线程组成的。线程有时也被称为并行运行在程序里的轻量级进程,线程被称为是轻量级进程是因为它的运行依赖与进程提供的上下文环境,并且使用的是进程的资源。
在一个进程里,线程的调度有抢占式或者非抢占的模式。
在抢占模式下,操作系统负责分配CPU时间给各个进程,一旦当前的进程使用完分配给自己的CPU时间,操作系统将决定下一个占用CPU时间的是哪一个线程。因此操作系统将定期的中断当前正在执行的线程,将CPU分配给在等待队列的下一个线程。
所以任何一个线程都不能独占CPU。每个线程占用CPU的时间取决于进程和操作系统。进程分配给每个线程的时间很短,以至于我们感觉所有的线程是同时执行的。实际上,系统运行每个进程的时间有2毫秒,然后调度其他的线程。它同时他维持着所有的线程和循环,分配很少量的CPU时间给线程。 线程的的切换和调度是如此之快,以至于感觉是所有的线程是同步执行的。