一、同步和互斥的基本概念现代操作系统基本都是多任务操作系统,即同时有大量可调度实体在运行,同时运行可能是真的同时运行(SMP架构中),也可能仅仅是操作系统提供的服务(通过将CPU时间分片,并将时间片分给不同的任务)。在多任务操作系统中,同时运行的多个任务可能
- 都需要访问/使用同一种资源
- 多个任务之间有依赖关系,某个任务的运行依赖于另一个任务
这两种情形是多任务编程中遇到的最基本的问题,也是多任务编程中的核心问题,同步和互斥就是用于解决这两个问题的。
- 互斥:是指散步在不同任务之间的若干程序片断,当某个任务运行其中一个程序片段时,其它任务就不能运行它们之中的任一程序片段,只能等到该任务运行完这个程序片段后才可以运行,最基本的场景就是对资源的同时写,为了保持资源的一致性,往往需要进行互斥访问。
- 同步:是指散步在不同任务之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务,最基本的场景就是任务之间的依赖,比如A任务的运行依赖于B任务产生的数据。
显然,同步是一种更为复杂的互斥,而互斥是一种特殊的同步。也就是说互斥是两个任务之间不可以同时运行,他们会相互排斥,必须等待一个线程运行完毕,另一个才能运行,而同步也是不能同时运行,但他是必须要安照某种次序来运行相应的线程(也是一种互斥)!因此互斥具有唯一性和排它性,但互斥并不限制任务的运行顺序,即任务是无序的。而同步的任务之间则有顺序关系。
在实际的设计、编码中,任务之间的相互依赖也就是情形2是比较容易发现的,而情形1就不那么明显了,同步/互斥中出现的问题也多和情形1相关。情形1是和资源访问相关的,要避免此类问题或者解决已经出现的此类问题首先要解决的问题是识别那类资源是被多个任务共享的,然后再使用同步/互斥的机制来保护这些资源的访问。简单的来说资源大概可以分为以下几类:
- 存储在存储器中的资源:这类资源不依赖于任务的运行,多以文件或数据库的形式存在于存储器中,它们对所有任务都是可见的(不考虑权限问题)。
- 内核中的资源:此类资源由内核创建和维护,对内核中的任务和获取了该资源的句柄的用户任务可见(对于内核创建的资源,如果用户任务想要使用它,往往都需要通过某种API类获取资源的句柄)。
- 用户任务中的资源:此类资源仅在该任务内可见,其它任务是无法访问该类资源的。
在进行设计、编码时我们可以首先对任务使用的资源进行分析,看它使用的资源属于那一类,如果有多个任务需要使用同一类资源,那么这里就需要进行同步/互斥了。(从这里的分析也可以看出,如果用户任务不需要使用内核中的资源也不许要使用存储器中的资源,那么它就不存在情形1所涉及的同步互斥需求)
二、用户程序编程中常见的多任务用户程序编程中常见的多任务有两种情形:
在这里可以将用户中的资源进行进一步的分类:
1. 进程中的资源:进程是操作系统分配资源的基本单位,进程的资源主要包括
- 地址空间(涉及到同步互斥的地址段主要是数据段和堆栈段)
- 打开的文件句柄
2. 线程中的资源:一个进程中的所有线程共享进程的地址空间(数据段/堆),打开的文件句柄,由线程独享的资源包括
三、进程和线程的基本概念1.进程进程是程序在计算机上的一次执行活动。当你运行一个程序,你就启动了一个进程。显然,程序是死的(静态的),进程是活的(动态的)。进程可以分为系统进程和用户进程。凡是用于完成操作系统的各种功能的进程就是系统进程,它们就是处于运行状态下的操作系统本身;其它进程就是用户进程。进程是操作系统进行资源分配的单位(比如文件句柄,虚拟地址空间等等)。
linux下创建子进程的调用是fork(),它功能就是产生子进程,其特别之处在于它会返回2次。
2.线程线程是可执行代码的可分派单元。这个名称来源于“执行的线索”的概念。在基于线程的多任务的环境中,所有进程有至少一个线程,但是它们可以具有多个任务。这意味着单个程序可以并发执行两个或者多个任务。
简而言之,线程就是把一个进程分为很多片,每一片都可以是一个独立的流程。这已经明显不同于多进程了,进程是一个拷贝的流程,而线程只是把一条河流截成很多条小溪。它没有拷贝这些额外的开销,但是仅仅是现存的一条河流,就被多线程技术几乎无开销地转成很多条小流程,它的伟大就在于它少之又少的系统开销。
多线程是为了使得多个线程并行的工作以完成多项任务,以提高系统的效率。
3.使用线程的好处使用线程的好处有以下几点:
- .提高应用程序的响应:可以对任何一个包含许多相互独立的活动的程序进行重新设计,以便将每个活动定义为一个线程。例如,多线程 GUI 的用户不必等待一个活动完成即可启动另一个活动。
- 更有效地使用多处理器:通常,要求并发线程的应用程序无需考虑可用处理器的数量。使用额外的处理器可以明显提高应用程序的性能。具有高度并行性的数值算法和数值应用程序(如矩阵乘法)在多处理器上通过多个线程实现时,运行速度会快得多。
- 改进程序结构:许多应用程序都以更有效的方式构造为多个独立或半独立的执行单元,而非整块的单个线程。多线程程序比单线程程序更能适应用户需求的变化。
- 占用较少的系统资源:多进程与多线程相比,每个进程都有一个完整的地址空间和操作环境状态。每个进程用于创建和维护大量状态信息的成本,与一个线程相比,无论是在时间上还是空间上代价都更高。此外,进程间所固有的独立性使得程序员需要花费很多精力来处理不同进程间的通信。
4.线程唯一的资源线程唯一的资源包括:
- 线程 ID
- 寄存器状态(包括 PC 和栈指针)
- 栈
- 信号掩码
- 优先级
- 线程专用存储
|