【面试题 计网&操作系统】

前言:以下内容均是学习他人博客+自己复习专用+自己理解,内容可能不太正确,不适合学习,欢迎大佬斧正。

一、进程线程的区别

       1)进程(运行的程序) 是系统进行资源分配和调用的最小单位,每一个进程都有自己独立的内存空间和系统资源

       2)线程 是进程的一条执行线路。程序执行的最小单位,是任务调度和执行的最小单位。

       3)联系 进程含有多条线程,线程只属于一个进程,一个进程多个线程之间是竞争关系,竞争独立的内存空间和系统资源。

       4) 区别 

            (1)  创建进程比创建线程的系统开销要大,进程的切换比线程的切换效率低

            (2)通信方面,进程之间的通信成本要比线程的高   进程(管道通信,信号量,信号,消息队列,共享内存,套接字) 线程(共享内存,信号量,全局变量)

问题1 同一进程下的线程共享了哪些资源

引出新问题:

问题2、什么是堆栈

搜的博客都不对,还是百度百科的概念比较清晰  百度百科

在计算机领域,堆栈是一个不容忽视的概念,是一种数据结构。堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除。在单片机应用中,堆栈是个特殊的存储区,主要功能是暂时存放数据和地址,通常用来保护断点和现场。

总而言之就是操作系统中会产生各种中断,对于各类中断信息,操作系统的原则是用堆栈 保护 断点和现场,后来先出的原则执行中断请求

草稿

视频链接:视频

进程是资源分配的最小单位,线程是cpu调度的最小单位,

进程包含许多线程,而线程只属于一个进程,创建进程的时候系统会为其分配地址空间、资源 所以创建进程的花费比较的高。

通信方面 同一进程下的线程可以通过 全局变量  静态变量等进行通信,而进程则需要 一些通信方式IPC  所以线程的通信更加方便。

之所以有线程的产生,主要是进程的并发不够

1. 共同点
功能上都是用于实现多任务并发程序设计的技术手段,线程的状态包括就绪、执行与阻塞,与进程类似。
从系统实现的角度看,进程实体和线程实体在Linux内核中都是有task_struct实现的,两者的创建最终都是调用系统函数clone(),

2. 区别
进程是资源分配的基本单位,线程是系统调度的基本单位,进程维护资源,线程是真正的执行体。

定义
进程是一个用户程序在同一数据集合上的一次执行过程,而在不同数据集合上或者同一数据集合的不同运行都是不同的进程。线程是进程上的一个实体,是系统调度的基本单位。

所属关系
线程只能属于一个进程,而进程可以创建多个线程,且最少创建一个主线程。

系统开销
线程开销小于进程开销,切换效率高于进程
,因为进程需要独立的数据段,代码段、扩展段等系统资源,创建时需要复制(写时复制)父进程的所有资源。而线程与其它线程共享进程的系统资源,每个线程只需要拥有自己的栈段和寄存器,用于存储局部变量和临时变量。但是进程因为有独立的数据段、堆栈段,所以更加稳定、安全。

资源分配
进程所维护的是程序所包含的资源(静态资源),比如:虚拟地址空间(代码、数据、堆、共享库)、文件系统信息、文件描述符表和信号处理程序等;线程所维护的运行相关的资源(动态资源),比如:运行栈、调度相关的控制信息、待处理的信号集等。

通信机制
进程间相互独立,互不打扰,因此通信方式较为复杂,包括Pipe(管道),Signal(信号),Semaphore(信号量),Message(消息队列),SharedMemory(共享内存),Socket(套接字),文件。(PS:PIC包括Semaphore,Message,SharedMemory)而线程之间由于共享进程数据段,所以通过全局变量来实现通信,当然访问时需要加锁。

控制权
线程可以销毁,挂起、恢复其它线程,也可以通过销毁主线程来销毁进程,而进程没有权利控制其父(子)进程的状态。子线程终止不会引起其它线程或者进程的终止,但进程(主线程)的终止能够引起所有子线程的终止,同时任何一个子线程执行exit()会引起进程中的全部线程同时灭亡。

linux系统内核实现
无论进程创建使用的fork()函数,还是线程创建使用的pthread_create()函数最终都是调用系统函数clone(),,只是通过传入不同的flag来设置是否共享父进程的资源。

同时,无论是进程实体还是线程实体,都是用linux内核中的进程控制表(process table)中的表项task_struct表示的。
(PS:这里解释一下Process Table,它的每一项都是task_struct结构,其物理实现是包含多个指针的静态数组,大小固定,所以内核有最大进程数。)
只是对于线程来说,其task_struct中的 TGID(thread group identifier)是主线程中的TGID,而主线程的TGID就是其自身的PID。
(CLONE_VM、CLONE_FS、CLONE_FILES、CLONE_SIGHAND、CLONE_THREAD、CLONE_SYSVSEM参数表示与父进程共享内存空间、文件系统、文件描述符,信号处理程序表和信号量列表。)

 

二、在浏览器中输入url回车后发生了什么

1、解析url获取域名

2、接着域名解析

3、浏览器与网站进行TCP连接

4、请求和传输数据

5、浏览器渲染页面

先浏览器缓存

系统缓存

路由器缓存

本地域名服务器

根域名服务器

顶级域名服务器

极限域名服务器

三、TCP和UDP的区别

    前期描述    TCP 和UDP都是工作在运输层的协议

UDP TCP
开销小 开销大
UDP是无连接通信  TCP是有连接通信
UDP支持一对多,多对多,多对一,多对一通信  TCP只能1对1通信
对应用层交付的报文直接打包  面向字节流
不可靠服务,无流量控制、无拥塞控制  可靠通信,支持流量控制、拥塞控制
首部开销小 只有8字节    首部20字节到60字节  (因为包含ack,FIN 序列号 确认序列号等等)

 1、由于TCP保证可靠的通信,头部比UDP的头部要长,因此开销比UDP的大

2、TCP通过三次握手建立可靠的通信信道进行通信,只能单播通信,UDP不建立信道

3、UDP直接给应用层报文添加UDP首部,形成用户数据报,然后进行发送(面向报文的)。TCP 对字节流进行编号,相当于把报文进行了分割小部分,分别发送 因此是面向字节流的

4、UDP 可能会发生丢包、误码,适用于实时应用。TCP流量控制(滑动窗口)、拥塞控制(慢启动、拥塞避免、快速重传、快速恢复)

tcp开销大,udp开销小

流量控制:滑动窗口
tcp有拥塞控制,可以慢开始,拥塞避免,快重传和快恢复,udp没有,不管网络是否拥塞,udp客户端都可以一直发
tcp数据完整,按时,按序到达,udp尽力满足
tcp延时高,适用于数据传输准确度要求高的场合,udp适用于数据传输量大,实时性要求高的场合

 

TCP实体:

源端口 目的端口

序号  解决乱序问题

确认序号  防止丢包

SYN发起一个连接

ACK 是回复

FIN是结束链接

RST是重新连接

1、TCP的11种状态描述

简单解释:

l  CLOSED:初始状态,表示TCP连接是“关闭着的”或“未打开的”。

l  LISTEN :表示服务器端的某个SOCKET处于监听状态,可以接受客户端的连接。

l  SYN_RCVD :表示服务器接收到了来自客户端请求连接的SYN报文。在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本上用netstat很难看到这种状态,除非故意写一个监测程序,将三次TCP握手过程中最后一个ACK报文不予发送。当TCP连接处于此状态时,再收到客户端的ACK报文,它就会进入到ESTABLISHED 状态。

l  SYN_SENT :这个状态与SYN_RCVD 状态相呼应,当客户端SOCKET执行connect()进行连接时,它首先发送SYN报文,然后随即进入到SYN_SENT 状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT 状态表示客户端已发送SYN报文。

l  ESTABLISHED :表示TCP连接已经成功建立。

l  FIN_WAIT_1 :这个状态得好好解释一下,其实FIN_WAIT_1 和FIN_WAIT_2 两种状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET进入到FIN_WAIT_1 状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2 状态。当然在实际的正常情况下,无论对方处于任何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1 状态一般是比较难见到的,而FIN_WAIT_2 状态有时仍可以用netstat看到。

l  FIN_WAIT_2 :上面已经解释了这种状态的由来,实际上FIN_WAIT_2状态下的SOCKET表示半连接,即有一方调用close()主动要求关闭连接。注意:FIN_WAIT_2 是没有超时的(不像TIME_WAIT 状态),这种状态下如果对方不关闭(不配合完成4次挥手过程),那这个 FIN_WAIT_2 状态将一直保持到系统重启,越来越多的FIN_WAIT_2 状态会导致内核crash。

l  TIME_WAIT :表示收到了对方的FIN报文,并发送出了ACK报文。 TIME_WAIT状态下的TCP连接会等待2*MSL(Max Segment Lifetime,最大分段生存期,指一个TCP报文在Internet上的最长生存时间。每个具体的TCP协议实现都必须选择一个确定的MSL值,RFC 1122建议是2分钟,但BSD传统实现采用了30秒,Linux可以cat /proc/sys/net/ipv4/tcp_fin_timeout看到本机的这个值),然后即可回到CLOSED 可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。(这种情况应该就是四次挥手变成三次挥手的那种情况)

l  CLOSING :这种状态在实际情况中应该很少见,属于一种比较罕见的例外状态。正常情况下,当一方发送FIN报文后,按理来说是应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。但是CLOSING 状态表示一方发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?那就是当双方几乎在同时close()一个SOCKET的话,就出现了双方同时发送FIN报文的情况,这是就会出现CLOSING 状态,表示双方都正在关闭SOCKET连接。

l  CLOSE_WAIT :表示正在等待关闭。怎么理解呢?当对方close()一个SOCKET后发送FIN报文给自己,你的系统毫无疑问地将会回应一个ACK报文给对方,此时TCP连接则进入到CLOSE_WAIT状态。接下来呢,你需要检查自己是否还有数据要发送给对方,如果没有的话,那你也就可以close()这个SOCKET并发送FIN报文给对方,即关闭自己到对方这个方向的连接。有数据的话则看程序的策略,继续发送或丢弃。简单地说,当你处于CLOSE_WAIT 状态下,需要完成的事情是等待你去关闭连接。

l  LAST_ACK :当被动关闭的一方在发送FIN报文后,等待对方的ACK报文的时候,就处于LAST_ACK 状态。当收到对方的ACK报文后,也就可以进入到CLOSED 可用状态了。

tcp的 11种状态 博客

图片来自:博客

四、DNS解析的过程

DNS 域名系统,将域名解析出IP地址。

先浏览器缓存 查询 是否之前已经解析过一次

系统缓存

路由器缓存

本地域名服务器

根域名服务器

顶级域名服务器

极限域名服务器

五、 GET POST区别,POST安全性更高为什么; 

六、三次握手 四次挥手

三次握手

客户端向服务端发送连接请求

服务端接受后发送  收到请求并确认

客户端收到指令 返回确认

四次挥手

客户端发送断开连接请求,

服务端收到发送确认,进入半关闭状态

之后服务端再次发送确认信息

客户端收到后 返回确认

七、分页管理和分段管理的区别

参考来自:博客

分页管理方式和分段管理方式的区别

1、目的

分页:页是信息的物理单位,分页是为了实现离散分配方式,以消减内存的外零头,提高内存的利用率。或者说,分页仅仅是由于系统管理的需要不是用户的需要。

分段:段是信息的逻辑单位,它含有一组其意义相对完整的信息,分段的目的是为了能更好的满足用户的需要。

2、长度

分页:页的大小固定且由系统决定,由系统把逻辑地址分为页号和页内地址两部分,是由机器硬件实现的,因而在系统中只能有一种大小的页面,

分段:段的长度不固定,决定于用户所编写的程序,通常由编译程序在对流程序进行编译时,根据信息的性质来划分。

3、地址空间

分页:作业地址空间是一维的,即单一的线性地址空间,程序员只需利用一个级衣服,即可表示一个地址。

分段:作业地址空间是二维的,程序员在表示一个地址时,既需给出段名,又需给出段内地址。

4、碎片

分页:有内部碎片,无外部碎片。

分段:有外部碎片,无内部碎片。

5、共享和动态链接

分页:不容易实现

分段:容易实现

自己理解:为什么说分页是一维的分段是二维的呢?

因为分页管理 的页大小是一样的,通过 地址/页大小 可以直接得到一维页号。

而分段的每段长度是不一样的,所以需要二维  段号、段内位移 

八、HTTPS的常见状态、HTTPS的加密机制

参考来自HTTPS的常见状态、HTTPS的加密机制  

1. HTTPS 概述

HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer 或 Hypertext Transfer Protocol Secure,超文本传输安全协议),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。https: URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。
众所周知,WEB服务存在http和https两种通信方式,http默认采用80作为通讯端口,对于传输采用不加密的方式;https默认采用443,对于传输的数据进行加密传输。目前主流的网站基本上开始默认采用HTTPS作为通信方式

2. 对称加密

对称加密算法的加密和解密都是用同一个密钥。

如果通信双方都各自持有同一个密钥,且没有别人知道,则两方的通信安全是可以被保证的(除非密钥被破解)。
然而,最大的问题就是这个密钥怎么让传输的双方知晓,同时不被别人知道。如果由服务器生成一个密钥并传输给浏览器,这个传输过程中密钥被别人劫持,之后他就能用密钥解开双方传输的任何内容。
如果浏览器内部预存了网站A的密钥,且可以确保除了浏览器和网站A,不会有任何外人知道该密钥,那理论上用对称加密是可以的。这样,浏览器只要预存好世界上所有HTTPS网站的密钥就可以了。显然,这样做是不现实的。
怎么办?解决这个问题,我们就需要非对称加密。

3. 非对称加密

基于对称加密存在的问题,又有了非对称加密。非对称加密算法需要一组密钥对,分别是公钥和私钥,这两个密钥是成对出现的。公钥加密的内容需要对应的私钥解密,私钥加密的内容需要对应的公钥解密。私钥由服务器自己保存,公钥发送给客户端。客户端拿到公钥后可以对请求进行加密后发送给服务端,这时候就算中间被截获,没有私钥也无法解密发送的内容,这样确保了客户端发送到服务端数据的安全。

4. 非对称加密改良方案

通过一组公钥私钥,已经可以保证单个方向传输的安全性,那用两组公钥私钥,是不是就能保证双向传输都安全了?请看下面的过程:

  1. 某网站拥有用于非对称加密的公钥A1、私钥A2;浏览器拥有用于非对称加密的公钥B1、私钥B2。
  2. 浏览器向网站服务器请求,服务器把公钥A1明文传输给浏览器。
  3. 浏览器把公钥B1明文传输给服务器。
  4. 之后浏览器向服务器传输的所有东西都用公钥A1加密,服务器收到后用私钥A2解密。由于只有服务器拥有私钥A2进行解密,所以能保证这条数据的安全。
  5. 服务器向浏览器传输的所有东西都用公钥B1加密,浏览器收到后用私钥B2解密。同上也可以保证这条数据的安全。

可见确实可行。抛开这里面仍有的漏洞不谈(下文会讲),HTTPS的加密却没使用这种方案,为什么?最主要的原因是非对称加密算法非常耗时,特别是加密解密一些较大数据的时候有些力不从心。而对称加密快很多。那我们能不能运用非对称加密的特性解决前面提到的对称加密的问题?

5. 非对称加密 + 对称加密

既然非对称加密耗时,我们考虑是否可以采用非对称加密+对称加密结合的方式,而且要尽量减少非对称加密的次数。
非对称加密、解密各只需一次的方法:

  1. 某网站拥有用于非对称加密的公钥A1、私钥A2。
  2. 浏览器向网站服务器请求,服务器把公钥A1明文给传输浏览器。
  3. 浏览器随机生成一个用于对称加密的密钥X,用公钥A1加密后传给服务器。
  4. 服务器拿到后用私钥A2解密得到密钥X。
  5. 这样双方就都拥有密钥X了,且别人无法知道它。之后双方所有数据都用密钥X加密解密即可。

HTTPS基本就是采用了这种方案。但还是有漏洞的。

6. 中间人攻击

中间人的确无法得到浏览器生成的对称密钥X,这个密钥本身被公钥A1加密,只有服务器才能用私钥A2进行解密。然而中间人却完全不需要拿到私钥A2就能劫持信息,请看:

  1. 某网站拥有用于非对称加密的公钥A1、私钥A2。
  2. 浏览器向网站服务器请求,服务器把公钥A1明文传输给浏览器。
  3. 中间人劫持到公钥A1,保存下来,把数据包中的公钥A1替换成自己伪造的公钥B1(它当然也拥有公钥B1对应的私钥B2)。
  4. 浏览器随机生成一个用于对称加密的密钥X,用公钥B1(浏览器不知道公钥被替换了)加密后传给服务器。
  5. 中间人劫持后用私钥B2解密得到密钥X,再用公钥A1加密后传给服务器。
  6. 服务器拿到后用私钥A2解密得到密钥X。

这样在双方都不会发现异常的情况下,中间人得到了对称密钥X。根本原因是浏览器无法确认自己收到的公钥是不是网站自己的。那么下一步就是解决这个问题:如何证明浏览器收到的公钥一定是该网站的公钥?

7. 数字证书

现实生活中,如果想证明某身份证号一定是小明的,怎么办?看身份证。这里政府机构起到了“公信”的作用,身份证是由它颁发的,它本身的权威可以对一个人的身份信息作出证明。互联网中也有这么一个公信机构,CA 机构。
网站在使用HTTPS前,需要向“CA机构”申请颁发一数字证书,数字证书里有证书持有者、证书持有者的公钥等信息。服务器把证书传输给浏览器,浏览器从证书里取公钥就可以了。然而这里又有一个显而易见的问题:证书本身的传输过程中,如何防止被篡改?即如何证明证书本身的真实性?数字证书怎么防伪呢?

8. 数字签名

我们把证书内容生成一份“签名”,比对证书内容和签名是否一致就能察觉是否被篡改。这种技术就叫数字签名。
下图中左侧是数字签名的制作过程,右侧是验证过程

数字签名的制作过程:

  1. CA拥有非对称加密的私钥和公钥。
  2. CA对证书明文信息进行hash。
  3. 对hash后的值用私钥加密,得到数字签名。

明文和数字签名共同组成了数字证书,这样一份数字证书就可以颁发给网站了。
那浏览器拿到服务器传来的数字证书后,如何验证它是不是真的?(有没有被篡改、掉包)

浏览器验证过程:

  1. 拿到证书,得到明文T1,数字签名S1。
  2. 用CA机构的公钥对S1解密(由于是浏览器信任的机构,所以浏览器保有它的公钥。详情见下文),得到S2。
  3. 用证书里说明的hash算法对明文T1进行hash得到T2。
  4. 比较S2是否等于T2,等于则表明证书可信。

为什么这样可以证明证书可信?
假设中间人篡改了证书的原文,由于他没有CA机构的私钥,所以无法得到此时加密后签名,无法相应地篡改签名。浏览器收到该证书后会发现原文和签名解密后的值不一致,则说明证书已被篡改,证书不可信,从而终止向服务器传输信息,防止信息泄露给中间人。

既然不可能篡改,那如果整个证书被掉包呢?
假设有另一个网站B也拿到了CA机构认证的证书,它想搞垮网站A,想劫持网站A的信息。于是它成为中间人拦截到了A传给浏览器的证书,然后替换成自己的证书,传给浏览器,之后浏览器就会错误地拿到B的证书里的公钥了,会导致上文提到的漏洞。
其实这并不会发生,因为证书里包含了网站A的信息,包括域名,浏览器把证书里的域名与自己请求的域名比对一下就知道有没有被掉包了。

制作数字签名时为什么需要hash一次?
最显然的是性能问题,前面我们已经说了非对称加密效率较差,证书信息一般较长,比较耗时。而hash后得到的是固定长度的信息(比如用md5算法hash后可以得到固定的128位的值),这样加密解密就会快很多。当然除此之外也有安全上的原因。

HTTPS必须在每次请求中都要先在SSL/TLS层进行握手传输密钥吗?
显然每次请求都经历一次密钥传输过程非常耗时,那怎么达到只传输一次呢?用session就可以。
服务器会为每个浏览器(或客户端软件)维护一个session ID,在TSL握手阶段传给浏览器,浏览器生成好密钥传给服务器后,服务器会把该密钥存到相应的session ID下,之后浏览器每次请求都会携带session ID,服务器会根据session ID找到相应的密钥并进行解密加密操作,这样就不必要每次重新制作、传输密钥了

9. HTTPS 工作原理

  1. client向server发送请求https://baidu.com,然后连接到server的443端口。

  2. 服务端必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面,这套证书其实就是一对公钥和私钥。

  3. 传送证书
    这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间、服务端的公钥,第三方证书认证机构(CA)的签名,服务端的域名信息等内容。

  4. 客户端解析证书
    这部分工作是由客户端的TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。如果证书没有问题,那么就生成一个随机值(密钥)。然后用证书对该随机值进行加密。

  5. 传送加密信息
    这部分传送的是用证书加密后的密钥(随机值),目的就是让服务端得到这个密钥(随机值),以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了。

  6. 服务端加密信息
    服务端用私钥解密,得到了客户端传过来的密钥(随机值),然后把内容通过该值进行对称加密。

  7. 传输加密后的信息
    这部分信息是服务端用密钥(随机值)对称加密后的信息,可以在客户端被还原。

  8. 客户端解密信息
    客户端用之前生成的密钥(随机值)解密服务端传过来的信息,于是获取了解密后的内容。

[参考文献]

  1. 百度百科 HTTPS
  2. 看完这篇文章,我奶奶都懂了https的原理 https://mp.weixin.qq.com/s/GZFiDQkZleSmriiNs4E1sA
  3. 彻底搞懂HTTPS的加密机制 https://zhuanlan.zhihu.com/p/43789231
  4. HTTPS原理和CA证书申请(满满的干货) https://blog.51cto.com/11883699/2160032

九.什么悲观锁,什么是乐观锁

      悲观锁就是数据库里的两类锁,写锁(排他锁)、读锁(共享锁)

一级封锁协议可避免 更新丢失问题 (更新覆盖) 加写锁

二级封锁协议 可避免 读入脏数据( 发生异常rollback)加读锁

三级封锁协议 可解决 不可重复读的问题 (读出第一次求和,只读导致可悲其他事务修改   读出第二次进行验算  验算答案不对)

加写锁和读锁

      乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则返回给用户错误的信息,让用户决定如何去做。类似对某一时刻的数据加了一个版本号 或者 时间戳  ,每次 冲突检测和数据更新 就行了

     悲观锁和乐观锁如何选择

在乐观锁与悲观锁的选择上面,主要看下两者的区别以及适用场景就可以了。

  1. 乐观锁并未真正加锁,效率高。一旦锁的粒度掌握不好,更新失败的概率就会比较高,容易发生业务失败。
  2. 悲观锁依赖数据库锁,效率低。更新失败的概率比较低。

随着互联网三高架构(高并发、高性能、高可用)的提出,悲观锁已经越来越少的被应用到生产环境中了,尤其是并发量比较大的业务场景。

十 死锁的四个必要条件?如何避免与预防死锁

参考博客:博客

一、什么是死锁

死锁是指多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。例如,在某一个计算机系统中只有一台打印机和一台输入 设备,进程P1正占用输入设备,同时又提出使用打印机的请求,但此时打印机正被进程P2 所占用,而P2在未释放打印机之前,又提出请求使用正被P1占用着的输入设备。这样两个进程相互无休止地等待下去,均无法继续执行,此时两个进程陷入死锁状态。

二、死锁产生的原因

1. 系统资源的竞争

系统资源的竞争导致系统资源不足,以及资源分配不当,导致死锁。

2. 进程运行推进顺序不合适

进程在运行过程中,请求和释放资源的顺序不当,会导致死锁。

三、死锁的四个必要条件

互斥条件:一个资源每次只能被一个进程使用,即在一段时间内某 资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。

请求与保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源 已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。

不可剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能 由获得该资源的进程自己来释放(只能是主动释放)。

循环等待条件: 若干进程间形成首尾相接循环等待资源的关系

这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

四、 死锁的避免与预防

1. 死锁避免

死锁避免的基本思想:系统对进程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,如果分配后系统可能发生死锁,则不予分配,否则予以分配,这是一种保证系统不进入死锁状态的动态策略。 
如果操作系统能保证所有进程在有限时间内得到需要的全部资源,则系统处于安全状态否则系统是不安全的。

    1. 安全状态是指:如果系统存在 由所有的安全序列{P1,P2,…Pn},则系统处于安全状态。一个进程序列是安全的,如果对其中每一个进程Pi(i >=1 && i <= n)他以后尚需要的资源不超过系统当前剩余资源量与所有进程Pj(j < i)当前占有资源量之和,系统处于安全状态则不会发生死锁。
    2. 不安全状态:如果不存在任何一个安全序列,则系统处于不安全状态。他们之间的对对应关系如下图所示:

 

下面我们来通过一个例子对安全状态和不安全状态进行更深的了解 

如上图所示系统处于安全状态,系统剩余3个资源,可以把其中的2个分配给P3,此时P3已经获得了所有的资源,执行完毕后还能还给系统4个资源,此时系统剩余5个资源所以满足(P2所需的资源不超过系统当前剩余量与P3当前占有资源量之和),同理P1也可以在P2执行完毕后获得自己需要的资源。 
如果P1提出再申请一个资源的要求,系统从剩余的资源中分配一个给进程P1,此时系统剩余2个资源,新的状态图如下:那么是否仍是安全序列呢那我们来分析一下 

系统当前剩余2个资源,分配给P3后P3执行完毕还给系统4个资源,但是P2需要5个资源,P1需要6个资源,他们都无法获得资源执行完成,因此找不到一个安全序列。此时系统转到了不安全状态。

2. 死锁预防

我们可以通过破坏死锁产生的4个必要条件来 预防死锁,由于资源互斥是资源使用的固有特性是无法改变的。

  1. 破坏“不可剥夺”条件:一个进程不能获得所需要的全部资源时便处于等待状态,等待期间他占有的资源将被隐式的释放重新加入到 系统的资源列表中,可以被其他的进程使用,而等待的进程只有重新获得自己原有的资源以及新申请的资源才可以重新启动,执行。
  2. 破坏”请求与保持条件“:第一种方法静态分配即每个进程在开始执行时就申请他所需要的全部资源。第二种是动态分配即每个进程在申请所需要的资源时他本身不占用系统资源。
  3. 破坏“循环等待”条件:采用资源有序分配其基本思想是将系统中的所有资源顺序编号,将紧缺的,稀少的采用较大的编号,在申请资源时必须按照编号的顺序进行,一个进程只有获得较小编号的资源才能申请较大编号的资源。

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/106949718