一、概述
进程的概念被提出后,OS一直都是以进程作为能拥有资源和独立运行的基本单位。之后又提出了比进程更小的能独立运行的基本单位
在操作系统中引入进程,为了使多个程序能并发执行,以提高资源利用率和系统吞吐量。那么在操作系统各种引入线程,则是为了减少程序在并发执行时所付出时空开销,使OS有更好地并发执行。
进程是一个资源拥有者,因而在创建、撤销和切换中,系统必须为之付出较大的时空开销。正因为如此,系统中的进程不宜过多,进程的切换频率不宜太高,这也就限制了并发程度的进一步提高。
于是OS设计师们想到,将进程了两个重要属性分开,由操作系统分开处理,即作为调度和分派的基本单位,不同时作为拥有资源的单位,即“轻”进程。
线程,CPU使用的基本单元。它由线程ID、程序计数器、寄存器集合和堆栈组成。
A thread is the basic unit to which the operating system allocates processor time.
A thread can execute any part of the process code, including parts currently being executed by another thread.
如果进程有多个控制线程,那么它能同时做多个任务。
1、多线程产生的动机
服务器接到请求时,若创建一个进程处理请求,会很麻烦,因为进程的创建消耗更多的资源等。所以不如创建一个具有多个线程的进程来代替。
2、多线程的优点
多线程编程有如下四类优点:
(1) 响应度高。部分线程阻塞,其他线程仍能继续执行。
(2) 资源共享。线程默认共享他们所属进程的内存和资源。
(3) 经济。进程创建所需要的内存和资源的分配比较昂贵。通常进程的创建开销比进程的维护开销更大,而且进程的上下文切换要比线程的上下文切换慢。
(4) 多处理器体系结构的利用。充分利用多处理器体系结构,以便每个进程可以并行运行在不同的处理器上。在单处理器体系结构上,CPU通过在线程之间的快速切换造成了并行执行的假象,但实际上任何时刻只有一个线程在运行。
3、用户线程和内核线程
用户线程的创建和调度在用户空间,无需内核的干预;
内核线程由OS直接支持:内核在其空间内执行线程创建、调度和管理。
二、多线程模型
1、多对一模型
将许多用户级线程映射到一个内核线程。
这种模型下,线程管理在用户空间进行,效率高。但是如果一个线程执行了阻塞系统调用,那整个进程就会阻塞。而且因为任一时刻只有一个线程能访问内核,多个线程不能运行在多处理器上。
2、一对一模型
将每个用户线程映射到一个内核线程。
提供了比多对一模型更好的并发功能,也允许多个线程能并行地运行在多核处理器系统上。
缺点是创建一个用户线程需要创建一个相应的内核线程,而创建内核线程的开销会影响应用程序的性能,所以这种模型的绝大多数实现限制了系统所支持的线程数量。
3、多对多模型
多路复用了许多用户级线程到同样数量或者更小数量的内核线程上。
开发人员可以创建任意多的必要用户线程,并且相应内核线程能在多处理器上并行执行。
4、系统调用fork和exec
系统调用fork用于创建独立、重复的进程。在多线程程序中,相关操作有所改变。
如果一个线程调用fork,那么新进程会复制所有线程还是只有单个线程?所以存在两种形式的fork调用。
exec呢?
5、线程池
总体思想:
在进程开始时创建一定数量的线程,并放入到池中坐以等待工作。当服务器收到请求时,它会唤醒池中的一个线程(如果有可用的线程),并将要处理的请求传递给它。一旦线程完成了它的服务,它会返回到池中再等待更多的工作。如果池中没有可用的线程,那么服务器会一直等待直到有空的线程为止
三、Pthread线程
Pthread指POSIX标准定义的,它地冠以线程创建API和同步API。是线程行为的规范么人不是实现。
通常,实现Pthread规范的库局限与基于UNIX的系统。Windows系统一般不支持Pthread。
四、Java 线程
多数OS会在内核级提供对线程的支持,Java是在语言级提供了对线程的创建和管理功能。
线程由JVM管理,而不是由用户级库或者内核管理,所以不好划分。
所有Java程序至少由一个控制线程组成。即使一个只包main方法的简单Java程序也是在JVM中作为一个单独线程运行的。
五、线程间的同步和通信
多线程OS中通常提供多种同步机制。
1、互斥锁
2、条件变量
3、信号量机制——与用于实现进程同步的信号量机制相同。
私有信号量、公有信号量。
六、线程的实现方式
线程在各个系统中的实现方式并不完全相同。
1、内核支持线程
2、用户级线程——仅存在与用户空间中