文章目录
1 进程、线程
1.1 区别
-
进程是资源分配的最小单位,线程是CPU调度的最小单位
-
一个程序中至少有一个进程,而一个进程中至少有一个线程
浏览器是多进程的,渲染进程是多线程的
-
进程是运行中的程序,线程是进程内部的一个执行序列
-
进程资源独占,线程资源共享;
1.2 绝妙例子——说明进程线程关系及特性(进程-火车,线程-车厢)
来源:知乎
-
线程在进程下行进:
单纯的车厢无法运行
-
一个进程可以包含多个线程:
一辆火车可以有多个车厢
-
不同进程间数据很难共享,同一进程下不同线程间数据很易共享:
一辆火车上的乘客很难换到另外一辆火车,比如站点换乘,A车厢换到B车厢很容易
-
进程要比线程消耗更多的计算机资源:
采用多列火车相比多个车厢更耗资源
-
进程间不会相互影响,一个线程挂掉大多数时候将导致整个进程挂掉
-
一列火车出事故不会影响到另外一列火车
-
但是如果一列火车上中间的一节车厢着火了,很可能将影响到所有车厢
例外情况:java中一个线程爆栈了或者OOM(Out Of Memory,内存溢出)了,其他线程不会受影响。例如坐票车厢特别拥挤,但不会影响到卧铺车厢
-
-
进程可以拓展到多机,线程最多适合多核:
不同火车可以开在多个轨道上,同一火车的车厢不能在行进的不同的轨道上
-
一个进程上的多个线程,在多核处理器系统中能并行执行:
一个列车上的多个车厢的事务可以由多位乘务员(多核)同时进行处理
-
进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。
(比如火车上的洗手间)-"互斥锁"
-
进程使用的内存地址可以限定使用量:
比如火车上的餐厅,最多只允许多少人进入,如果满了需要在门口等,等有人出来了才能进去-“信号量”
1.3 进程、线程状态
-
5大线程状态
-
所有函数:
start()-开始
yield()-让步
resume():重新开始
notify():通知
suspend():挂起、延缓
synchronized():同步
-
1、新建状态:新创建一个线程对象。
-
2、就绪状态(start、yield):线程对象创建后,其他线程调用了该对象的 start() 方法。该状态的线程位于“可运行的线程池”中,变得可运行,只等待获取CPU的使用权。即在就绪状态的进程除了CPU之外,其他的运行所需资源都已全部获得。
-
3、运行状态:就绪状态的线程获取了CPU,执行程序代码。
-
4、阻塞状态(join):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。
-
5、死亡状态:线程执行完了或者因异常退出了 run() 方法,该线程结束生命周期。
-
-
3大进程状态
-
-
1、就绪态:进程已经具备运行条件,但是CPU还没有分配过来。
-
2、运行态:进程占用CPU,并在CPU上运行。
-
3、阻塞态:进程因等待某件事发生而暂时不能运行
-
🚩补充:sleep wait join yield区别
- sleep:Thread类的方法,让出cpu调度,不释放锁,调用后进入阻塞态
- yield:Thread类的方法,让出cpu调度,让同优先级的线程有执行的机会,如果没有则立刻继续执行。调用后进入可运行态
- wait:Object类的方法,让出cpu调度,释放锁,调用后进入休眠态(notify / interrupt()后进入阻塞态)
- join:特殊的wait,让出cpu调度,释放锁,调用后进入阻塞态,当前运行线程调用另一个线程的join方法,当前线程进入阻塞状态直到另一个线程运行结束再继续执行。
1.4 进程、线程的同步
-
进程同步:信号量、管程、消息传递
- 1、信号量:用于进程间传递信号的一个整数值。两个或多个进程可以通过简单的信号进行合作,一个进程可以被迫在某一位置停止,直到它接收到一个特定的信号。
在信号量上只有三种操作可以进行:初始化,P操作和V操作,P操作(递减操作)可以用于阻塞一个进程,V操作(增加操作)可以用于解除阻塞一个进程。
- 2、管程(只允许一个线程进入):管程是由一个或多个过程、一个初始化序列和局部数据组成的软件模块,原理如下:
- 局部数据变量只能被管程的过程访问,任何外部过程都不能访问。
- 一个进程通过调用管程的一个过程进入管程。
- 在任何时候,只能有一个进程在管程中执行,调用管程的任何其他进程都被阻塞,以等待管程可用。
- 3、消息传递(生产者-消费者):进程间进程消息传递所需要的最小操作
- 一个进程以消息的形式给另一个指定的目标进程发送消息;
- 进程通过执行receive原语接收消息,receive原语中指明发送消息的源进程和消息。
-
线程同步:互斥量、信号量、事件、临界区
两个或多个共享关键资源的线程的并发执行。应该同步线程以避免关键的资源使用冲突。-
互斥量(Mutex):采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。比如Java中的synchronized关键词和各种Lock 都是这种机制。
-
信号量(Semphares) :它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量
-
事件(Event) :通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作
-
临界区(Critical Section):保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么在有一个线程进入后,其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。
-
1.5 进程、线程的死锁
一组竞争系统资源或相互通信的进程相互的永久阻塞
-
进程 / 线程产生死锁的四个必要条件(须同时满足):
-
(1) 互斥条件:一个资源每次只能被一个进程使用。
-
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
-
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能被强行剥夺。
-
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
-
解读:
东西一次只能一个人用(1),大家排队排成一圈(4),不插队(3),不离队(2)
-
-
解决死锁的四种方式
-
鸵鸟策略:不采取任务措施。因为解决死锁问题的代价很高,因此鸵鸟策略这种不采取任务措施的方案会获得更高的性能。
-
死锁检测与死锁恢复:检测主要是查看当前是否出现了环路等待;恢复可以通过杀死进程或者利用回滚
-
死锁预防:在程序运行之前破坏发生死锁的条件,预防发生死锁
比如说破坏环路等待:可以给资源统一编号,进程只能按编号顺序来请求资源。 -
死锁避免 :使用银行家算法,假设给进程分配资源,看能不能找到一个安全序列,如果系统处于不安全状态,不一定会发生死锁;但是死锁时,系统一定处于不安全状态
-
2 IO多路复用
2.1 select、poll、epoll 复用方式
-
select==>时间复杂度O(n)
它仅仅知道了,有I/O事件发生了,却并不知道是哪那几个流(可能有一个,多个,甚至全部),我们只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对他们进行操作。所以select具有O(n)的无差别轮询复杂度,同时处理的流越多,无差别轮询时间就越长。 -
poll==>时间复杂度O(n)
poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态, 但是它没有最大连接数的限制,原因是它是基于链表来存储的. -
epoll==>时间复杂度O(1)
epoll可以理解为event poll,不同于忙轮询和无差别轮询,epoll会把哪个流发生了怎样的I/O事件通知我们。所以我们说epoll实际上是事件驱动(每个事件关联上fd)的,此时我们对这些流的操作都是有意义的。(复杂度降低到了O(1))
- select,poll,epoll都是IO多路复用的机制。I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。
2.2 epoll 机制底层数据结构,为什么能够做到O(1)复杂度(待补充
)
3 Linux 常用命令🌈
- 目录切换
cd
- 目录查看
ls [-al]
- 目录操作【增,删,改,查】
创建目录【增】
mkdir
删除目录或文件【删】rm
目录修改【改】mv
和cp
搜索目录【查】find
4 常见调度算法
- 先来先服务(FCFS)调度算法:先到先得
既可以用于作业调度也可以用于进程调度。 - 短作业优先(SJF)调度算法:快的先来
从就绪队列中选择一个估计运行时间最短的进程,将处理机分配给它,使之立即执行,直到完成或发生某事件而阻塞时,才释放处理机。 - 优先级调度算法
- 高响应比优先调度算法:等的越久、要求服务时间越短的先来
- 时间片轮转调度算法:先到先得,且限时
也是先来先服务的原则,但仅能运行一个时间片,如100ms。在使用完一个时间片后,即使进程并未完成其运行,它也必须释放出(被剥夺)处理机给下一个就绪的进程,而被剥夺的进程返回到就绪队列的末尾重新排队,等候再次运行。 - 多级反馈队列调度算法(集合了前几种算法的优点)
时间片轮转调度算法和优先级调度算法的综合和发展