操作系统 进程与线程

1、进程

1.1 进程简介

进程是对运行时程序的封装,是系统进行资源调度和分配的基本单位,实现了操作系统的并发。
一个程序至少有一个进程。

1.2 进程状态

  • 就绪状态(ready):进程具备运行条件,等待系统分配处理器以便运行。
  • 运行状态(running):进程占有处理器正在运行。
  • 阻塞状态(waiting):指进程不具备运行条件,正在等待某个事件的完成。

通常,一个进程在创建后将处于就绪状态。每个进程在执行过程中,任意时刻当且仅当处于上述三种状态之一。同时,在一个进程执行过程中,它的状态将会发生改变。引起进程状态转换的具体原因如下:
在这里插入图片描述

  1. 运行状态一一等待状态:等待使用资源或某事件发生,如等待外设传输;等待人工干预。
  2. 等待状态一一就绪状态:资源得到满足或某事件己经发生,如外设传输结束;人工干预完成。
  3. 运行状态一一就绪状态:运行时间片到,或出现有更高优先权进程。
  4. 就绪状态一一运行状态:CPU空闲时被调度选中一个就绪进程执行。

注意:

  • 只有就绪态和运行态可以相互转换,其它的都是单向转换。就绪状态的进程通过调度算法从而获得 CPU 时间,转为运行状态;而运行状态的进程,在分配给它的 CPU 时间片用完之后就会转为就绪状态,等待下一次调度。
  • 阻塞状态是缺少需要的资源从而由运行状态转换而来,但是该资源不包括 CPU 时间,缺少 CPU 时间会从运行态转换为就绪态。

1.3 进程间通信的方式

进程间通信(Interprocess communication),即IPC,就是在不同进程之间传播或交换信息,共有7种:

  1. 管道(pipe):管道用于具有父子关系的进程通信,是一种半双工的通信方式
  2. 命名管道(FIFO):无论两个进程间有没有关系,都可以通信,也是一种半双工的通信方式
  3. 消息队列(message queue):由消息组成的链表,克服了管道以及命名管道中消息量有限的缺点。对消息队列具有写权限的进程可以按照一定的规则向消息队列中添加信息,对消息队列具有读权限的进程可以从消息队列中读取信息
  4. 信号(signal):用于通知进程某个事件已经发生
  5. 信号量(semophere):进程间或同一进程不同线程间实现同步或者互斥的手段
  6. 共享内存(shared memory):进程间最快的一种通信方式,需要同步方式,例如互斥锁和信号量
  7. 套接字(socket):可用于不同机器间的进程通信

1.4 进程同步

首先介绍两个概念:

  • 临界资源:一次仅允许一个进程使用的资源称为临界资源。
    在操作系统引论中介绍操作系统的四大特性之一“共享”时曾提到,对于资源的共享有两种方式:互斥共享和同时访问。其中需要互斥访问的资源就是临界资源;所谓互斥访问,就是指在进程A对资源X的处理结束前,其他进程不允许对X进行处理;这里的临界资源既包括硬件资源也包括软件资源;
  • 临界区:对临界资源进行访问的那段代码称为临界区
    为了互斥访问临界资源,每个进程在进入临界区之前,需要先进行检查,检查是否可以访问互斥资源,这一部分代码即为进入区;在退出临界区时,需要释放对临界资源的占有,这一部分代码即为退出区;然后我们把剩下的其余代码成为剩余区

其次,同步机制应该遵循以下四个规则:

  • 空则让进:临界资源如果处于空闲状态,那么该进程可以进入其临界区;
  • 忙则等待:临界资源如果处于被占用状态,那么该进程需要等待临界资源被释放;
  • 有限等待:进程在有限时间内可以进入自己的临界区,以避免陷入“死等”状态;
  • 让权等待:当进程不能进入自己的临界区时,需要让出处理机,以避免陷入“忙等”状态;

最后,常见的同步机制有:硬件同步机制、信号量机制、管程机制等。

  1. 硬件同步机制
    利用软件方法可以解决进程互斥进入临界区的问题,但是有一定的难度和局限性,现已很少使用。

  2. 信号量机制
    信号量(Semaphore)是一个整型变量,可以对其执行 down 和 up 操作,也就是常见的 P 和 V 操作。

    • down : 如果信号量大于 0 ,执行 -1 操作;如果信号量等于 0,进程睡眠,等待信号量大于 0;
    • up :对信号量执行 +1 操作,唤醒睡眠的进程让其完成 down 操作。

    down 和 up 操作需要被设计成原语,不可分割,通常的做法是在执行这些操作的时候屏蔽中断。
    如果信号量的取值只能为 0 或者 1,那么就成为了 互斥量(Mutex) ,0 表示临界区已经加锁,1 表示临界区解锁。

  3. 管程机制
    使用信号量机制实现的生产者消费者问题需要客户端代码做很多控制,而管程把控制的代码独立出来,不仅不容易出错,也使得客户端代码调用更容易。

1.5 进程调度

不同环境的调度算法目标不同,因此需要针对不同环境来讨论调度算法。

1.5.1 批处理系统

批处理系统没有太多的用户操作,在该系统中,调度算法目标是保证吞吐量和周转时间(从提交到终止的时间)。

  1. 先来先服务 first-come first-serverd(FCFS)
    非抢占式的调度算法,按照请求的顺序进行调度。
    有利于长作业,但不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。
  2. 短作业优先 shortest job first(SJF)
    非抢占式的调度算法,按估计运行时间最短的顺序进行调度。
    长作业有可能会饿死,处于一直等待短作业执行完毕的状态。因为如果一直有短作业到来,那么长作业永远得不到调度。
  3. 最短剩余时间优先 shortest remaining time next(SRTN)
    最短作业优先的抢占式版本,按剩余运行时间的顺序进行调度。 当一个新的作业到达时,其整个运行时间与当前进程的剩余时间作比较。如果新的进程需要的时间更少,则挂起当前进程,运行新的进程。否则新的进程等待。

1.5.2 交互式系统

交互式系统有大量的用户交互操作,在该系统中调度算法的目标是快速地进行响应。

  1. 时间片轮转
    将所有就绪进程按 FCFS 的原则排成一个队列,每次调度时,把 CPU 时间分配给队首进程,该进程可以执行一个时间片。当时间片用完时,由计时器发出时钟中断,调度程序便停止该进程的执行,并将它送往就绪队列的末尾,同时继续把 CPU 时间分配给队首的进程。
    时间片轮转算法的效率和时间片的大小有很大关系:
    • 因为进程切换都要保存进程的信息并且载入新进程的信息,如果时间片太小,会导致进程切换得太频繁,在进程切换上就会花过多时间。
    • 而如果时间片过长,那么实时性就不能得到保证。

在这里插入图片描述

  1. 优先级调度
    为每个进程分配一个优先级,按优先级进行调度。
    为了防止低优先级的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级。

  2. 多级反馈队列
    一个进程需要执行 100 个时间片,如果采用时间片轮转调度算法,那么需要交换 100 次。
    多级队列是为这种需要连续执行多个时间片的进程考虑,它设置了多个队列,每个队列时间片大小都不同,例如 1,2,4,8,…。进程在第一个队列没执行完,就会被移到下一个队列。这种方式下,之前的进程只需要交换 7 次。
    每个队列优先权也不同,最上面的优先权最高。因此只有上一个队列没有进程在排队,才能调度当前队列上的进程。
    可以将这种调度算法看成是时间片轮转调度算法和优先级调度算法的结合。
    在这里插入图片描述

1.5.3 实时系统

实时系统要求一个请求在一个确定时间内得到响应。

分为硬实时和软实时,前者必须满足绝对的截止时间,后者可以容忍一定的超时。

1.6 进程特性

1.6.1 进程优点

提供了多道编程,提高计算机CPU的利用率。多道编程的理解:可以将多个进程同时加载到内存中,在操作系统的调度下,可以实现并发的执行。这样就可以提供了CPU的利用率。

1.6.2 进程缺点

  • 进程只能在一个时间内执行一件事,如果想执行多件事,进程就无能为力了。

  • 进程在执行的过程中如果堵塞,例如等待用户输入信息,整个进程就会挂起,即使进程中有些工作不依赖输入的数据,也将无法执行。

2、线程

2.1 线程简介

线程是进程的子任务,是CPU调度和分派的基本单位,用于保证程序的实时性,实现进程内部的并发。
一个进程至少有一个线程,线程依赖于进程而存在。

2.2 线程状态

线程与进程类似,在整个运行期间具有三种状态:

  • 就绪状态(ready):线程已经具备了各种执行条件,若获得 CPU 便可以立即执行。
  • 运行状态(running):线程已经获得了 CPU,并处于执行过程中。
  • 阻塞状态(waiting):线程在执行中,因某事件出现而受到阻塞,处于暂停执行状态。

线程之间的转换和进程状态之间的转换相同。由于线程不是资源的拥有单位,因此没有挂起状态。此外,若进程由于系统性能原因而被挂起,则它所包含的所有线程都必须对换出去。

2.3 线程间通信的方式

线程间通信的方式如下:

  1. 锁机制:包括互斥锁、读写锁、条件变量
    1. 互斥锁:提供了以排他方式防止数据结构被并发修改的方法
    2. 读写锁:允许多个线程同时读共享数据,而对写操作是互斥的
    3. 条件变量:可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用
  2. 信号机制:类似进程间的信号处理
  3. 信号量机制:包括无名线程信号量和命名线程信号量

线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。

2.4 线程同步

线程同步,即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作。

线程同步的几种方式如下:

  1. 互斥量:互斥量有两种状态:解锁和加锁。当一个线程(或进程)需要访问临界区时,它调用互斥锁。如果该互斥量当前是解锁的(即临界区可用),此调用成功,调用线程可以自由进入该临界区。另一方面,如果该互斥量已经加锁,调用线程被阻塞,直到在临界区中的线程完成并调用互斥锁。如果多个线程被阻塞在该互斥量上,将随机选择一个线程并允许它获得锁。
  2. 信号(事件):通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作。
  3. 信号量:它允许同一时刻多个线程访问同一资源,但是需要一个计数器来控制可以使用某共享资源的线程数目。

互斥量跟信号量的区别与联系:

  • 互斥量用于线程的互斥。 信号量用于线程的同步。这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别。

  • 互斥量值只能为0/1,信号量值可以为非负整数。也就是说,一个互斥量只能用于一个资源的互斥访问,它不能实现多个资源的多线程互斥问题。信号量可以实现多个同类资源的多线程互斥和同步。

总结

  1. 互斥:是指某一资源同时只允许一个访问者对其进行访问。但互斥无法使访问者按照某种规则进行访问。
  2. 同步:线程之间的运行必须按照某种规定来执行,执行的次序依赖于要完成的特定的任务。
  3. 同步是一种更为复杂的互斥,而互斥是一种特殊的同步。

2.5 线程调度

计算机通常只有一个CPU,在任意时刻只能执行一条机器指令,每个线程只有获得CPU的使用权才能执行指令。所谓多线程的并发运行,其实是指从宏观上看,各个线程轮流获得CPU的使用权,分别执行各自的任务。在运行池中,会有多个处于就绪状态的线程在等待CPU,JAVA虚拟机的一项任务就是负责线程的调度,线程调度是指按照特定机制为多个线程分配CPU的使用权。

有两种调度模型:分时调度模型和抢占式调度模型。

  • 分时调度模型:让所有的线程轮流获得cpu的使用权,并且平均分配每个线程占用的CPU的时间片。
  • 抢占式调度模型(Java虚拟机采用):优先让可运行池中优先级高的线程占用CPU,如果可运行池中的线程优先级相同,那么就随机选择一个线程,使其占用CPU。处于运行状态的线程会一直运行,直至它不得不放弃CPU。

2.6 线程特性

2.6.1 线程优点

  • 创建一个新线程的代价要比创建一个新进程小的多

  • 与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多

  • 线程占用的资源要比进程少很多

  • 能充分利用多处理器的可并行数量

  • 在等待慢速I/O操作结束的同时,程序可执行其他的计算任务

  • 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现

  • I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作

2.6.2 线程缺点

  • 创建一个新线程的代价要比创建一个新进程小的多

  • 与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多

  • 线程占用的资源要比进程少很多

  • 能充分利用多处理器的可并行数量

  • 在等待慢速I/O操作结束的同时,程序可执行其他的计算任务

  • 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现

  • I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作

3、进程与线程的区别

  1. 拥有资源

    进程是资源分配的基本单位,但是线程不拥有资源,线程可以访问隶属进程的资源。

  2. 调度

    线程是独立调度的基本单位,在同一进程中,线程的切换不会引起进程切换,从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。

  3. 系统开销

    由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O 设备等,所付出的开销远大于创建或撤销线程时的开销。类似地,在进行进程切换时,涉及当前执行进程 CPU 环境的保存及新调度进程 CPU 环境的设置,而线程切换时只需保存和设置少量寄存器内容,开销很小。

  4. 通信方面

    线程间可以通过直接读写同一进程中的数据进行通信,但是进程通信需要借助 IPC。

最重要的区别是:进程拥有独立的内存单元,而线程共享进程的内存单元

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赈川

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值