在传统的操作系统中,每个进程都有一个地址空间和一个控制线程。事实上,这是大部分进程的定义。不过,在许多情况下,经常存在同一地址空间中运行多个控制线程的情形,这些线程就像是分离的进程。下面我们就着重探讨一下什么是线程
线程的使用或许这个疑问也是你的疑问,为什么要在进程的基础上再创建一个线程的概念,准确的说,这其实是进程模型和线程模型的讨论,回答这个问题,可能需要分三步来回答
多线程之间会共享同一块地址空间和所有可用数据的能力,这是进程所不具备的
线程要比进程更轻量级,由于线程更轻,所以它比进程更容易创建,也更容易撤销。在许多系统中,创建一个线程要比创建一个进程快 10 - 100 倍。
第三个原因可能是性能方面的探讨,如果多个线程都是 CPU 密集型的,那么并不能获得性能上的增强,但是如果存在着大量的计算和大量的 I/O 处理,拥有多个线程能在这些活动中彼此重叠进行,从而会加快应用程序的执行速度
经典的线程模型进程中拥有一个执行的线程,通常简写为 线程(thread)。线程会有程序计数器,用来记录接着要执行哪一条指令;线程实际上 CPU 上调度执行的实体。
下图我们可以看到三个传统的进程,每个进程有自己的地址空间和单个控制线程。每个线程都在不同的地址空间中运行
下图中,我们可以看到有一个进程三个线程的情况。每个线程都在相同的地址空间中运行。
线程不像是进程那样具备较强的独立性。同一个进程中的所有线程都会有完全一样的地址空间,这意味着它们也共享同样的全局变量。由于每个线程都可以访问进程地址空间内每个内存地址,因此一个线程可以读取、写入甚至擦除另一个线程的堆栈。线程之间除了共享同一内存空间外,还具有如下不同的内容
上图左边的是同一个进程中每个线程共享的内容,上图右边是每个线程中的内容。也就是说左边的列表是进程的属性,右边的列表是线程的属性。
线程之间的状态转换和进程之间的状态转换是一样的。
每个线程都会有自己的堆栈,如下图所示
线程系统调用进程通常会从当前的某个单线程开始,然后这个线程通过调用一个库函数(比如 thread_create )创建新的线程。线程创建的函数会要求指定新创建线程的名称。创建的线程通常都返回一个线程标识符,该标识符就是新线程的名字。
当一个线程完成工作后,可以通过调用一个函数(比如 thread_exit)来退出。紧接着线程消失,状态变为终止,不能再进行调度。在某些线程的运行过程中,可以通过调用函数例如 thread_join ,表示一个线程可以等待另一个线程退出。这个过程阻塞调用线程直到等待特定的线程退出。在这种情况下,线程的创建和终止非常类似于进程的创建和终止。
另一个常见的线程是调用 thread_yield,它允许线程自动放弃 CPU 从而让另一个线程运行。这样一个调用还是很重要的,因为不同于进程,线程是无法利用时钟中断强制让线程让出 CPU 的。
POSIX 线程POSIX 线程 通常称为 pthreads是一种独立于语言而存在的执行模型,以及并行执行模型。