1.死锁是什么?什么情况下产生?怎么解决?
死锁条件
1.互斥:坑(资源)只能一个人蹲
2.请求与保持:申请去隔壁蹲坑,没同意之前就先自己占着原来坑不动
3.不剥夺:我蹲着坑,锁着门,没人敢把我撵出去
4.循环等待:你等着占我的坑,我等着占别人的坑,而自己都先占着原来的坑不动
处理方法
1.预防:坡坏条件 请求保持(一次性把所有资源都申请了,要么逐步释放) 不剥夺(申请失败就释放) 循环等待(排队优先级)
2.避免:避免系统进入不安全状态(不能满足所有蹲坑者对顺利蹲坑的要求)
安全序列:是指一个进程序列{P1,…,Pn}是安全的,即对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。(我将来的需求可以满足,要么直接有要么可以抢)
安全状态:如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。安全状态一定是没有死锁发生。
不安全状态:不存在一个安全序列。不安全状态不一定导致死锁。
银行家算法涉及的数据结构:
可用资源向量Available。Available[j]=k;有j类型妹子k个;
最大需求矩阵Max。Max[n,j]=k;小n对j类型妹子最多需要k个;
分配矩阵Allocation。Allocation[n,j]=k;小n已经泡了j类型妹子k个;
当前需求矩阵Need。Need[n,j]=k;小n还需要泡j类型妹子几个;
银行家算法的伪算法:
设request是编号为x的进程的请求向量;如果request[j]=k,表示进程x对编号为j的资源请求量为k;
1.如果request[j]<=need[x,j],转向2;否则请求出错,因为它申请的资源数量超过当前它需要的数量,认为这是一个失败的请求;
2.如果request[j]<=Available[j],转向3;否则表示系统当前没有足够的资源可以分配,x进程需要等待;
3.试着将编号为j的资源分配给进程x,更新相关数据结构:
Available[j]=Available[j]-request[j];
Allocation[x,j]=Allocation[x,j]+request[j];
Need[x,j]=Need[x,j]-request[j];
4.进入安全性检测程序(该程序试图找到一个安全序列;如果找到,说明这次分配之后系统仍然是安全的,否则这次分配无效,因为系统进入了不安全状态)
3.检测:通过资源图,了解资源的使用和请求情况
4.解除:抢占资源,或者选择代价最小的进行终止
2.线程进程区别
1.进程:就是运行着的程序,一个有独立功能的程序段,被加载进内存并准备执行就是一个进程。
2.线程:线程是进程的一个子集,执行进程的一个任务,一个进程多个线程,线程只属于一个进程。
3.进程通信方式
1. 管道pipe:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。一端写一端读 只存在于内存
2. 命名管道FIFO:有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信 文件系统中
3.消息队列:存放在内核中。一个消息队列由一个标识符(即队列ID)来标识
独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。
随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取
4.信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。
5.共享内存(Shared Memory),指两个或多个进程共享一个给定的存储区。
共享内存是最快的一种 IPC,因为进程是直接对内存进行存取。
因为多个进程可以同时操作,所以需要进行同步。
信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。
4.线程通信方式
1.通过线程之间共享变量的方式
这个就有必要说下 wait(),notify(),以及notifyAll() 这三个方法
这三个方法都是属于Object的方法;所以所有类都可以继承这三方法;
wait()方法使得当前线程必须要等待,等到另外一个线程调用notify()或者notifyAll()方法。
notify()方法会唤醒一个等待当前对象的锁的线程(随机)。而notifyAll()顾名思义;就是唤醒所有在等待中的方法;
wait()和notify()方法要求在调用时线程已经获得了对象的锁,因此对这两个方法的调用需要放在synchronized方法或synchronized块中。
有朋友可能会有疑问:为何这三个不是Thread类声明中的方法,而是Object类中声明的方法(当然由于Thread类继承了Object类,所以Thread也可以调用者三个方法)?其实这个问题很简单,由于每个对象都拥有monitor(即锁),所以让当前线程等待某个对象的锁,锁是对象的,只有对象能释放,当然应该通过这个对象来操作了。而不是用当前线程来操作,因为当前线程可能会等待多个线程的锁,这么多个锁,wait释放哪一个呢?如果通过线程来操作,就非常复杂了。
2.同步
3.while轮询