1、进程和线程的区别?
- 调度: 进程是资源管理的基本单位,线程是程序执行的基本单位。
- 切换: 线程上下文切换比进程上下文切换要快得多。
- 拥有资源: 进程是拥有资源的一个独立单位,线程不拥有系统资源,但是可以访问隶属于进程的资源。
- 系统开销: 创建或撤销进程时,系统都要为之分配或回收系统资源,如内存空间,
I/O
设备等,OS
所付出的开销显著大于在创建或撤销线程时的开销,进程切换的开销也远大于线程切换的开销。
用户态到内核态的方式
- 系统调用: 用户态主动要求切换到内核态,从而使用内核提供的各项服务。比如,
Linux
创建进程时中用户态的fork()
会调用到内核态的sys_fork()
和do_fork()
等; - 中断: 外设完成用户请求后(如完成读写操作),发出中断信号,
CPU
暂停执行下一条要执行的指令,而去执行中断处理程序; - 异常: 如发生缺页异常等,同样会切换到内核态进行处理。
2、协程与线程的区别
- 线程和进程都是同步机制,而协程是异步机制。
- 线程是抢占式,而协程是非抢占式的。需要用户释放使用权切换到其他协程,因此同一时间其实只有一个协程拥有运行权,相当于单线程的能力。
- 一个线程可以有多个协程,一个进程也可以有多个协程。
- 协程不被操作系统内核管理,而完全是由程序控制。线程是被分割的
CPU
资源,协程是组织好的代码流程,线程是协程的资源。但协程不会直接使用线程,协程直接利用的是执行器关联任意线程或线程池。 - 协程能保留上一次调用时的状态。
3、并发与并行有什么区别?
- 并发就是在一段时间内,多个任务都会被处理;但在某一时刻,只有一个任务在执行。单核处理器可以做到并发。比如有两个进程
A
和B
,A
运行一个时间片之后,切换到B
,B
运行一个时间片之后又切换到A
。因为切换速度足够快,所以宏观上表现为在一段时间内能同时运行多个程序。 - 并行就是在同一时刻,有多个任务在执行。这个需要多核处理器才能完成,在微观上就能同时执行多条指令,不同的程序被放到不同的处理器上运行,这个是物理上的多个进程同时进行。
4、进程与线程的切换流程?
答: 进程切换分两步:
1、切换页表以使用新的地址空间,一旦去切换上下文,处理器中所有已经缓存的内存地址一瞬间都作废了。
2、切换内核栈和硬件上下文。
对于Linux来说,线程和进程的最大区别就在于地址空间,对于线程切换,线程仅需切换内核栈和硬件上下文。
因为每个进程都有自己的虚拟地址空间,而线程是共享所在进程的虚拟地址空间的,因此同一个进程中的线程进行线程切换时不涉及虚拟地址空间的转换。
5、线程切换的原因
- 线程的
CPU
时间片用完 - 垃圾回收
- 有更高优先级的线程需要运行
- 线程自已调用了
sleep
、yield
、wait
、park
、synchronized
、lock
等方法
6、线程切换的流程
答: 线程切换时需要知道在这之前当前线程已经执行到哪条指令了,所以需要记录程序计数器的值,另外比如说线程正在进行某个计算的时候被挂起了,那么下次继续执行的时候需要知道之前挂起时变量的值时多少,因此需要记录CPU寄存器的状态。 所以一般来说,线程上下文切换过程中会记录程序计数器、 CPU
寄存器状态等数据。
进程 | 线程 | 协程 | |
切换者 | 操作系统 | 操作系统 | 用户(编程者/应用程序) |
切换时机 | 根据操作系统自己的切换策略,用户不感知 | 根据操作系统自己的切换策略,用户不感知 | 用户自己(的程序决定) |
切换内容 | 页全局目录 内核栈 硬件上下文 | 内核栈 硬件上下文 | 内核栈 硬件上下文 |
切换内容的保存 | 保存于内核栈中 | 保存于内核栈中 | 保存于用户自己的变量 (用户栈或者堆) |
切换过程 | 用户态—内核态—用户态 | 用户态—内核态—用户态 | 用户态(没有陷入内核态) |
切换效率 | 低 | 中 | 高 |
线程切换需要保存哪些上下文?
答:线程在切换的过程中需要保存当前线程Id
、线程状态、堆栈、寄存器状态等信息。其中寄存器主要包括SP
、PC
和EAX
等寄存器,其主要功能如下:
SP
: 堆栈指针,指向当前栈的栈顶地址;PC
: 程序计数器,存储下一条将要执行的指令;EAX
: 累加寄存器,用于加法乘法的缺省寄存器。
7、如何减少线程间的切换
答:既然上下文切换会导致额外的开销,因此减少上下文切换次数便可以提高多线程程序的运行效率。减少上下文切换的方法有无锁并发编程、CAS
算法、使用最少线程和使用协程。
- 无锁并发编程: 多线程竞争时,会引起上下文切换,所以多线程处理数据时,可以用一些办法来避免使用锁,如将数据的
ID
按照Hash
取模分段,不同的线程处理不同段的数据; CAS
算法:Java
的Atomic
包使用CAS
算法来更新数据,而不需要加锁;- 使用最少线程: 避免创建不需要的线程,比如任务很少,但是创建了很多线程来处理,这样会造成大量线程都处于等待状态;
- 协程: 在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换。
8、为什么虚拟地址空间切换会比较耗时?
答:进程都有自己的虚拟地址空间,把虚拟地址转换为物理地址需要查找页表,页表查找是一个很慢的过程,因此通常使用Cache
来缓存常用的地址映射,这样可以加速页表查找,这个Cache
就是TLB
(translation Lookaside Buffer
,TLB
本质上就是一个Cache
,是用来加速页表查找的)。
由于每个进程都有自己的虚拟地址空间,那么显然每个进程都有自己的页表,那么当进程切换后页表也要进行切换,页表切换后TLB就失效了,
Cache
失效导致命中率降低,那么虚拟地址转换为物理地址就会变慢,表现出来的就是程序运行会变慢,而线程切换则不会导致TLB
失效,因为线程无需切换地址空间,因此我们通常说线程切换要比较进程切换块,原因就在这里。
9、进程间的通信方式有哪些?
-
管道: 管道这种通讯方式有两种限制,一是半双工的通信,数据只能单向流动,二是只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
管道可以分为两类:匿名管道和命名管道。匿名管道是单向的,只能在有亲缘关系的进程间通信;命名管道以磁盘文件的方式存在,可以实现本机任意两个进程通信。
-
信号: 信号是一种比较复杂的通信方式,信号可以在任何时候发给某一进程,而无需知道该进程的状态。
-
信号量:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
-
消息队列: 消息队列是消息的链接表,包括
Posix
消息队列和System V
消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。 -
共享内存: 共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的
IPC
方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。 -
Socket
: 与其他通信机制不同的是,它可用于不同机器间的进程通信。
10、进程间的通信方式的优缺点?
- 管道: 速度慢,容量有限;
Socket
: 任何进程间都能通讯,但速度慢;- 消息队列: 容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题;
- 信号量: 不能传递复杂消息,只能用来同步;
- 共享内存区: 能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存。
11、进程间同步的方式?
11.1、临界点
答:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
- 优点: 保证在某一时刻只有一个线程能访问数据的简便办法。
- 缺点: 虽然临界区同步速度很快,但却只能用来同步本进程内的线程,而不可用来同步多个进程中的线程。
11.2、互斥量
答:为协调共同对一个共享资源的单独访问而设计的。互斥量跟临界区很相似,比临界区复杂,互斥对象只有一个,只有拥有互斥对象的线程才具有访问资源的权限。
- 优点: 使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。
- 缺点:
- 互斥量是可以命名的,也就是说它可以跨越进程使用,所以创建互斥量需要的资源更多,所以如果只为了在进程内部是用的话使用临界区会带来速度上的优势并能够减少资源占用量。
- 通过互斥量可以指定资源被独占的方式使用,但如果有下面一种情况通过互斥量就无法处理,比如现在一位用户购买了一份三个并发访问许可的数据库系统,可以根据用户购买的访问许可数量来决定有多少个线程/进程能同时进行数据库操作,这时候如果利用互斥量就没有办法完成这个要求,信号量对象可以说是一种资源计数器。
11.3、信号量
答: 为控制一个具有有限数量用户资源而设计。 它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。互斥量是信号量的一种特殊情况,当信号量的最大资源数=1就是互斥量了。
- 优点: 适用于对
Socket
(套接字)程序中线程的同步。 - 缺点:
- 信号量机制必须有公共内存,不能用于分布式操作系统,这是它最大的弱点;
- 信号量机制功能强大,但使用时对信号量的操作分散, 而且难以控制,读写和维护都很困难,加重了程序员的编码负担;
- 核心操作
P-V
分散在各用户程序的代码中,不易控制和管理,一旦错误,后果严重,且不易发现和纠正。
11.4、事件
答:用来通知线程有一些事件已发生,从而启动后继任务的开始。
优点: 事件对象通过通知操作的方式来保持线程的同步,并且可以实现不同进程中的线程同步操作。
12、线程同步的方式有哪些?
- 临界区: 当多个线程访问一个独占性共享资源时,可以使用临界区对象。拥有临界区的线程可以访问被保护起来的资源或代码段,其他线程若想访问,则被挂起,直到拥有临界区的线程放弃临界区为止,以此达到用原子方式操作共享资源的目的。
- 事件: 事件机制,则允许一个线程在处理完一个任务后,主动唤醒另外一个线程执行任务。
- 互斥量: 互斥对象和临界区对象非常相似,只是其允许在进程间使用,而临界区只限制与同一进程的各个线程之间使用,但是更节省资源,更有效率。
- 信号量: 当需要一个计数器来限制可以使用某共享资源的线程数目时,可以使用“信号量”对象。
区别:
- 互斥量与临界区的作用非常相似,但互斥量是可以命名的,也就是说互斥量可以跨越进程使用,但创建互斥量需要的资源更多,所以如果只为了在进程内部是用的话使用临界区会带来速度上的优势并能够减少资源占用量 。因为互斥量是跨进程的互斥量一旦被创建,就可以通过名字打开它。
- 互斥量,信号量,事件都可以被跨越进程使用来进行同步数据操作
13、线程的分类(从线程的运行空间来说)?
- 内核级线程:这类线程依赖于内核,又称为内核支持的线程或轻量级进程。无论是在用户程序中的线程还是系统进程中的线程,它们的创建、撤销和切换都由内核实现。比如英特尔
i5-8250U
是4核8线程,这里的线程就是内核级线程 - 用户级线程:它仅存在于用户级中,这种线程是不依赖于操作系统核心的。应用进程利用线程库来完成其创建和管理,速度比较快,操作系统内核无法感知用户级线程的存在。
14、什么是临界区,如何解决冲突?
答:每个进程中访问临界资源的那段程序称为临界区,一次仅允许一个进程使用的资源称为临界资源。
解决冲突的办法:
- 如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入,如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待;
- 进入临界区的进程要在有限时间内退出。
- 如果进程不能进入自己的临界区,则应让出
CPU
,避免进程出现“忙等”现象。
15、进程调度的策略有哪几种?
-
先来先服务:非抢占式的调度算法,按照请求的顺序进行调度。有利于长作业,但不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。另外,对
I/O
密集型进程也不利,因为这种进程每次进行I/O
操作之后又得重新排队。 -
短作业优先:非抢占式的调度算法,按估计运行时间最短的顺序进行调度。长作业有可能会饿死,处于一直等待短作业执行完毕的状态。因为如果一直有短作业到来,那么长作业永远得不到调度。
-
最短剩余时间优先:最短作业优先的抢占式版本,按剩余运行时间的顺序进行调度。 当一个新的作业到达时,其整个运行时间与当前进程的剩余时间作比较。如果新的进程需要的时间更少,则挂起当前进程,运行新的进程。否则新的进程等待。
-
时间片轮转:将所有就绪进程按
FCFS
的原则排成一个队列,每次调度时,把CPU
时间分配给队首进程,该进程可以执行一个时间片。当时间片用完时,由计时器发出时钟中断,调度程序便停止该进程的执行,并将它送往就绪队列的末尾,同时继续把CPU
时间分配给队首的进程。时间片轮转算法的效率和时间片的大小有很大关系:因为进程切换都要保存进程的信息并且载入新进程的信息,如果时间片太小,会导致进程切换得太频繁,在进程切换上就会花过多时间。 而如果时间片过长,那么实时性就不能得到保证。
-
优先级调度:为每个进程分配一个优先级,按优先级进行调度。为了防止低优先级的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级。
16、进程有哪些状态?
答:进程一共有5
种状态,分别是创建、就绪、运行(执行)、终止、阻塞。
- 运行态→阻塞态:往往是由于等待外设,等待主存等资源分配或等待人工干预而引起的。
- 阻塞态→就绪态:则是等待的条件已满足,只需分配到处理器后就能运行。
- 运行态→就绪态:不是由于自身原因,而是由外界原因使运行状态的进程让出处理器,这时候就变成就绪态。例如时间片用完,或有更高优先级的进程来抢占处理器等。
- 就绪态→运行态:系统按某种策略选中就绪队列中的一个进程占用处理器,此时就变成了运行态。
17、硬链接和软链接有什么区别?
- 硬链接: 硬链接就是在目录下创建一个条目,记录着文件名与
inode
编号,这个inode
就是源文件的inode
。删除任意一个条目,文件还是存在,只要引用数量不为0
。但是硬链接有限制,它不能跨越文件系统,也不能对目录进行链接。 - 软连接: 符号链接文件保存着源文件所在的绝对路径,在读取时会定位到源文件上,可以理解为
Windows
的快捷方式。当源文件被删除了,链接文件就打不开了。因为记录的是路径,所以可以为目录建立符号链接。