目录
操作系统的发展史
操作系统中为什么会出现进程?
EAINC是世界上第一台通用计算机,它于1946年2月14日在美国宣告诞生。在计算机刚出现的时候,是为了解决数学计算的问题,因为很多大量的计算通过人力去完成是很耗时间和人力成本的。
在最初的时候,计算机只能接受一些特定的指令,用户输入一个指令,计算机就做一个操作。当用户在思考或者输入数据时,计算机就在等待。显然这样效率和很低下,因为很多时候,计算机处于等待用户输入的状态。
基于上述情况,出现了批处理操作系统
它把一系列需要操作的指令预先写下来,形成一个清单,然后一次性交给计算机,计算机不断地去读取指令来进行相应的操作。用户可以将需要执行的多个程序写在磁带(因为早起的存储介质没有磁盘,只有磁带)上,然后交由计算机去读取并逐个地执行这些程序,并将输出结果写到另一个磁带上。
批处理操作系统的缺点
假如有两个任务A和B,任务A在执行到一半的过程中,需要读取大量的数据输入(I/O操作,很耗时),而此时CPU只能静静地等待任务A读取完数据才能继续执行,这样就白白浪费了CPU资源。
进程
批处理的反思
人们想能否在任务A读取数据的过程中,让任务B去执行,当任务A读取完数据之后,让任务B暂停,然后让任务A继续执行?那么问题来了:原来每次都是一个程序在计算机里面运行,也就说内存中始终只有一个程序的运行数据。如果想要任务A在执行I/O操作的时候,让任务B去执行,必然内存中要装入多个程序,那么如何处理呢?多个程序使用的数据如何进行辨别呢?并且当一个程序运行暂停后,后面如何恢复到它之前执行的状态呢?
进程的诞生
人们发明了进程,用进程来对应一个程序,每个进程对应一定的内存地址空间,并且只能使用它自己的内存空间,各个进程间互不干扰。并且进程保存了程序每个时刻的运行状态,这样就为进程切换提供了可能。当进程暂时时,它会保存当前进程的状态(比如进程标识、进程的使用的资源等),在下一次重新切换回来时,便根据之前保存的状态进行恢复,然后继续执行
线程
进程的缺点
一个进程在一个时间段内只能做一件事情,如果一个进程有多个子任务,只能逐个地去执行这些子任务。
对于一个电商系统而言,它不仅要把图像数据显示在画面上,还要与服务端进行通信获取商品数据,还要处理用户的交互操作。如果一个进程中,每次只能执行一个任务,对于电商系统而言,用户可能需要一直等待,直到所有的操作在单个进程中处理完。显然,这样的系统,显示是无法满足用户的需求的。
线程的诞生
可不可以将进程中这些子任务分开执行呢?即在系统获取商品数据的同时,如果用户点击了某个按钮,则会暂停获取图像数据,而先去响应用户的操作(因为用户的操作往往执行时间很短),在处理完用户操作之后,再继续获取商品数据。于是人们发明了线程。
让一个线程去执行一个子任务,这样一个进程就包括了多个线程,每个线程负责一个独立的子任务,这样在用户点击按钮的时候,就可以暂停获取商品数据的线程,让图像线程响应用户的操作,响应完之后再切换回来,让获取图像的线程得到CPU资源。从而让用户感觉系统是同时在做多件事情的,满足了用户对实时性的要求。
简单的说
——进程让操作系统的并发性成为可能。
——线程让进程的内部并发成为可能。
⚠️注意
- 一个进程虽然包括多个线程,但是这些线程是共同享有进程占有的资源和地址空间的
- 进程是操作系统进行资源分配的基本单位
- 线程是操作系统进行调度的基本单位
问题:
由于多个线程是共同占有所属进程的资源和地址空间的,那么就会存在一个问题:
如果多个线程要同时访问某个资源,怎么处理?
这个问题相信大部分人都了解,随着我们一点一点的学习并发编程的内容,后面也将会有更深的印象。
多线程的性能一定就优于单线程吗?
不一定,要看具体的任务以及计算机的配置
对于单核CPU,如果是CPU密集型任务,如解压文件,多线程的性能反而不如单线程性能。解压文件要一直占用CPU资源,如果用多线程,线程切换导致的开销反而会让性能下降。
多核CPU,多线程肯定优于单线程,多个线程能够更加充分利用每个核的资源。 虽然多线程能够提升程序性能,但是相对于单线程来说,它的编程要复杂地多,要考虑线程安全问题。因此,在实际编程过程中,要根据实际情况具体选择。
总结
操作系统的设计,因此可以归结为三点:
(1)以多进程形式,允许多个任务同时运行;
(2)以多线程形式,允许每个任务分成不同的部分运行;
(3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。