写给大忙人看的死锁详解(3)

简介: 写给大忙人看的死锁详解(3)

其他问题


下面我们来探讨一下其他问题,包括 通信死锁、活锁是什么、饥饿问题和两阶段加锁


两阶段加锁


虽然很多情况下死锁的避免和预防都能处理,但是效果并不好。随着时间的推移,提出了很多优秀的算法用来处理死锁。例如在数据库系统中,一个经常发生的操作是请求锁住一些记录,然后更新所有锁定的记录。当同时有多个进程运行时,就会有死锁的风险。


一种解决方式是使用 两阶段提交(two-phase locking)。顾名思义分为两个阶段,一阶段是进程尝试一次锁定它需要的所有记录。如果成功后,才会开始第二阶段,第二阶段是执行更新并释放锁。第一阶段并不做真正有意义的工作。


如果在第一阶段某个进程所需要的记录已经被加锁,那么该进程会释放所有锁定的记录并重新开始第一阶段。从某种意义上来说,这种方法类似于预先请求所有必需的资源或者是在进行一些不可逆的操作之前请求所有的资源。


不过在一般的应用场景中,两阶段加锁的策略并不通用。如果一个进程缺少资源就会半途中断并重新开始的方式是不可接受的。


通信死锁


我们上面一直讨论的是资源死锁,资源死锁是一种死锁类型,但并不是唯一类型,还有通信死锁,也就是两个或多个进程在发送消息时出现的死锁。进程 A 给进程 B 发了一条消息,然后进程 A 阻塞直到进程 B 返回响应。假设请求消息丢失了,那么进程 A 在一直等着回复,进程 B 也会阻塞等待请求消息到来,这时候就产生死锁


尽管会产生死锁,但是这并不是一个资源死锁,因为 A 并没有占据 B 的资源。事实上,通信死锁并没有完全可见的资源。根据死锁的定义来说:每个进程因为等待其他进程引起的事件而产生阻塞,这就是一种死锁。相较于最常见的通信死锁,我们把上面这种情况称为通信死锁(communication deadlock)


通信死锁不能通过调度的方式来避免,但是可以使用通信中一个非常重要的概念来避免:超时(timeout)。在通信过程中,只要一个信息被发出后,发送者就会启动一个定时器,定时器会记录消息的超时时间,如果超时时间到了但是消息还没有返回,就会认为消息已经丢失并重新发送,通过这种方式,可以避免通信死锁。


但是并非所有网络通信发生的死锁都是通信死锁,也存在资源死锁,下面就是一个典型的资源死锁。


当一个数据包从主机进入路由器时,会被放入一个缓冲区,然后再传输到另外一个路由器,再到另一个,以此类推直到目的地。缓冲区都是资源并且数量有限。如下图所示,每个路由器都有 10 个缓冲区(实际上有很多)。


image.png


假如路由器 A 的所有数据需要发送到 B ,B 的所有数据包需要发送到 D,然后 D 的所有数据包需要发送到 A 。没有数据包可以移动,因为在另一端没有缓冲区可用,这就是一个典型的资源死锁。


活锁


你会发现一个很有意思的事情,死锁就跟榆木脑袋一样,不会转弯。我看过古代的一则故事:


image.png


如果说死锁很痴情的话,那么活锁用一则成语来表示就是 弄巧成拙


某些情况下,当进程意识到它不能获取所需要的下一个锁时,就会尝试礼貌的释放已经获得的锁,然后等待非常短的时间再次尝试获取。可以想像一下这个场景:当两个人在狭路相逢的时候,都想给对方让路,相同的步调会导致双方都无法前进。


现在假想有一对并行的进程用到了两个资源。它们分别尝试获取另一个锁失败后,两个进程都会释放自己持有的锁,再次进行尝试,这个过程会一直进行重复。很明显,这个过程中没有进程阻塞,但是进程仍然不会向下执行,这种状况我们称之为 活锁(livelock)


饥饿


与死锁和活锁的一个非常相似的问题是 饥饿(starvvation)。想象一下你什么时候会饿?一段时间不吃东西是不是会饿?对于进程来讲,最重要的就是资源,如果一段时间没有获得资源,那么进程会产生饥饿,这些进程会永远得不到服务。


我们假设打印机的分配方案是每次都会分配给最小文件的进程,那么要打印大文件的进程会永远得不到服务,导致进程饥饿,进程会无限制的推后,虽然它没有阻塞。


总结


死锁是一类通用问题,任何操作系统都会产生死锁。当每一组进程中的每个进程都因等待由该组的其他进程所占有的资源而导致阻塞,死锁就发生了。这种情况会使所有的进程都处于无限等待的状态。


死锁的检测和避免可以通过安全和不安全状态来判断,其中一个检测方式就是银行家算法;当然你也可以使用鸵鸟算法对死锁置之不理,但是你肯定会遭其反噬。


也可以在设计时通过系统结构的角度来避免死锁,这样能够预防死锁;也可以破坏死锁的四个条件来破坏死锁。资源死锁并不是唯一性的死锁,还有通信间死锁,可以设置适当的超时时间来完成。


活锁和死锁的问题有些相似,它们都是一种进程无法继续向下执行的状态。由于进程调度策略导致尝试获取进程的一方永远无法获得资源后,进程会导致饥饿的出现。


尾声



提出一个勘误,已反馈给出版社


image.png



相关文章
|
SQL 数据采集 关系型数据库
大数据采集和抽取怎么做?这篇文章终于说明白了!
数据是数据中台\数据平台核心中的核心,因此数据汇聚必然是数据中台/平台的入口,本文详细讲述采集模块的方方面面、采集框架的使用选型以及企业真实落地
大数据采集和抽取怎么做?这篇文章终于说明白了!
|
.NET C# 容器
WPF自定义LED风格数字显示控件
原文:WPF自定义LED风格数字显示控件 版权声明:本文为博主原创文章,转载请注明作者和出处 https://blog.csdn.net/ZZZWWWPPP11199988899/article/details/52895167 ...
1920 0
|
容灾 关系型数据库 数据库
阿里云RDS服务巴黎奥运会赛事系统,助力云上奥运稳定运行
2024年巴黎奥运会,阿里云作为官方云服务合作伙伴,提供了稳定的技术支持。云数据库RDS通过备份恢复、实时监控、容灾切换等产品能力,确保了赛事系统的平稳运行。
 阿里云RDS服务巴黎奥运会赛事系统,助力云上奥运稳定运行
|
10月前
|
机器学习/深度学习 人工智能 安全
GLM-Zero:智谱AI推出与 OpenAI-o1-Preview 旗鼓相当的深度推理模型,开放在线免费使用和API调用
GLM-Zero 是智谱AI推出的深度推理模型,专注于提升数理逻辑、代码编写和复杂问题解决能力,支持多模态输入与完整推理过程输出。
543 24
GLM-Zero:智谱AI推出与 OpenAI-o1-Preview 旗鼓相当的深度推理模型,开放在线免费使用和API调用
|
Java Apache Maven
将word文档转换成pdf文件方法
在Java中,将Word文档转换为PDF文件可采用多种方法:1) 使用Apache POI和iText库,适合处理基本转换需求;2) Aspose.Words for Java,提供更高级的功能和性能;3) 利用LibreOffice命令行工具,适用于需要开源解决方案的场景。每种方法都有其适用范围,可根据具体需求选择。
|
存储 Kubernetes Docker
使用 Docker 搭建碎片化知识卡片-Memos
Memos 是一个功能全面、易于使用的开源知识库和社交平台,适合个人和企业使用。它支持标签、过滤、搜索和多账户管理,提供多种隐私设置和后端存储选择,支持单点登录和 Docker 部署,注重数据的安全性和私密性。
421 12
使用 Docker 搭建碎片化知识卡片-Memos
|
算法 计算机视觉 Python
计算机视觉的应用场景
计算机视觉的应用场景
540 0
|
11月前
|
人工智能 自动驾驶 安全
“第四次工业革命”-AI革命
“AI变革”被誉为“第四次工业革命”。中国在AI领域持续发力,占亚太地区AI支出的五成,预计2023年市场规模将达到147.5亿美元,约占全球市场的十分之一。IDC预测,中国生成式AI市场年复合增长率将达86.2%。国内企业如百度、阿里、清华等在AI技术研发和应用方面取得显著进展,推动了无人驾驶、送餐机器人、无人快递车等应用场景的发展。尽管AI带来了降本增效,但也引发了就业和社会压力。总体而言,中国在AI领域的投入和发展势头强劲,未来前景广阔。
905 0
“第四次工业革命”-AI革命
|
人工智能 搜索推荐 开发者
社区供稿 | 大模型恋爱神器!16种MBTI自由定制,北大ChatLaw团队出品
北大团队新作,让大模型拥有个性!而且还是自定义那种,16种MBTI都能选。
|
数据采集 JavaScript 前端开发
动态内容抓取指南:使用Scrapy-Selenium和代理实现滚动抓取
在传统的网络爬虫中,静态网页内容很容易抓取,但对于通过JavaScript加载的动态内容,通常需要借助浏览器进行模拟访问。Scrapy-Selenium是一款结合了Scrapy和Selenium功能的库,可以实现模拟浏览器行为,从而实现抓取动态内容的目的。
794 0
动态内容抓取指南:使用Scrapy-Selenium和代理实现滚动抓取